/
githubmirror
/
fwupd
Обзор
Документация
Войти
/
githubmirror
/
fwupd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
plugins/devlink/fu-devlink-backend.c
196 строк
6 KB
Jiri Pirko
devlink: get serial number and use it as backend id
26 сен 2025, 11:16
26 сен 2025, 11:16
c34d62b
Код
Авторство
О чём код?
/* * Copyright 2025 NVIDIA Corporation & Affiliates * * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "config.h" #include "fu-devlink-backend.h" #include "fu-devlink-device.h" struct _FuDevlinkBackend { FuBackend parent_instance; }; G_DEFINE_TYPE(FuDevlinkBackend, fu_devlink_backend, FU_TYPE_BACKEND) static FuDevice * fu_devlink_backend_create_pci_parent(FuDevlinkBackend *self, const gchar *bus_name, const gchar *dev_name, GError **error) { FuContext *ctx = fu_backend_get_context(FU_BACKEND(self)); FuBackend *udev_backend = NULL; g_autofree gchar *pci_sysfs_path = NULL; g_autofree gchar *pci_sysfs_real = NULL; g_autoptr(FuDevice) pci_device = NULL; g_autoptr(GError) error_local = NULL; /* get the udev backend to create PCI parent device */ udev_backend = fu_context_get_backend_by_name(ctx, "udev", &error_local); if (udev_backend == NULL) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "udev backend not available: %s", error_local->message); return NULL; } /* construct PCI sysfs path from bus_name (e.g., "pci/0000:01:00.0") */ pci_sysfs_path = g_strdup_printf("/sys/bus/pci/devices/%s", dev_name); pci_sysfs_real = fu_path_make_absolute(pci_sysfs_path, error); if (pci_sysfs_real == NULL) return NULL; /* create PCI device from sysfs path */ pci_device = fu_backend_create_device(udev_backend, pci_sysfs_real, &error_local); if (pci_device == NULL) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "failed to create PCI device for %s: %s", pci_sysfs_path, error_local->message); return NULL; } /* ensure PCI device is probed to get vendor/device info */ if (!fu_device_probe(pci_device, error)) { g_prefix_error_literal(error, "failed to probe PCI device: "); return NULL; } return g_steal_pointer(&pci_device); } static FuDevice * fu_devlink_backend_create_netdevsim_parent(FuDevlinkBackend *self, const gchar *bus_name, const gchar *dev_name, GError **error) { FuContext *ctx = fu_backend_get_context(FU_BACKEND(self)); g_autoptr(FuDevice) netdevsim_device = NULL; g_autofree gchar *physical_id = NULL; /* create a fake netdevsim parent device for testing */ netdevsim_device = fu_device_new(ctx); /* set netdevsim device properties */ physical_id = g_strdup_printf("netdevsim-%s", dev_name); fu_device_set_physical_id(netdevsim_device, physical_id); fu_device_set_name(netdevsim_device, "Network Device Simulator"); return g_steal_pointer(&netdevsim_device); } FuDevice * fu_devlink_backend_device_added(FuDevlinkBackend *self, const gchar *bus_name, const gchar *dev_name, const gchar *serial_number, GError **error) { FuContext *ctx = fu_backend_get_context(FU_BACKEND(self)); FuDevice *old_devlink_device; g_autoptr(FuDevice) devlink_device = NULL; g_autoptr(FuDevice) parent_device = NULL; g_return_val_if_fail(FU_IS_DEVLINK_BACKEND(self), NULL); g_return_val_if_fail(bus_name != NULL, NULL); g_return_val_if_fail(dev_name != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); /* only support PCI and netdevsim buses */ if (g_strcmp0(bus_name, "pci") == 0) { parent_device = fu_devlink_backend_create_pci_parent(self, bus_name, dev_name, error); if (parent_device == NULL) return NULL; } else if (g_strcmp0(bus_name, "netdevsim") == 0) { parent_device = fu_devlink_backend_create_netdevsim_parent(self, bus_name, dev_name, error); if (parent_device == NULL) return NULL; } else { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "unsupported bus type: %s (only 'pci' and 'netdevsim' are supported)", bus_name); return NULL; } /* create devlink device */ devlink_device = fu_devlink_device_new(ctx, bus_name, dev_name, serial_number); if (devlink_device == NULL) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "failed to create devlink device"); return NULL; } /* only add one device for the PCI card, use serial number as backend id */ if (serial_number != NULL) fu_device_set_backend_id(devlink_device, serial_number); /* in case the device with the same backend id already exists, skip this one */ old_devlink_device = fu_backend_lookup_by_id(FU_BACKEND(self), fu_device_get_backend_id(devlink_device)); if (old_devlink_device != NULL) { g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "device with the same backend id already exists: %s", fu_device_get_backend_id(devlink_device)); return NULL; } /* incorporate information from parent device (without setting hierarchy) */ fu_device_incorporate(devlink_device, parent_device, FU_DEVICE_INCORPORATE_FLAG_BASECLASS | FU_DEVICE_INCORPORATE_FLAG_VENDOR | FU_DEVICE_INCORPORATE_FLAG_VENDOR_IDS | FU_DEVICE_INCORPORATE_FLAG_VID | FU_DEVICE_INCORPORATE_FLAG_PID); /* only add the devlink device to the backend - parent is managed by its own backend */ fu_backend_device_added(FU_BACKEND(self), devlink_device); return g_steal_pointer(&devlink_device); } void fu_devlink_backend_device_removed(FuDevlinkBackend *self, FuDevice *devlink_device) { g_return_if_fail(FU_IS_DEVLINK_BACKEND(self)); g_return_if_fail(FU_IS_DEVICE(devlink_device)); fu_backend_device_removed(FU_BACKEND(self), devlink_device); } static void fu_devlink_backend_init(FuDevlinkBackend *self) { } static void fu_devlink_backend_class_init(FuDevlinkBackendClass *klass) { } FuBackend * fu_devlink_backend_new(FuContext *ctx) { return FU_BACKEND(g_object_new(FU_TYPE_DEVLINK_BACKEND, "name", "devlink", "context", ctx, "device-gtype", FU_TYPE_DEVLINK_DEVICE, NULL)); }