static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev *udev = udev_device_get_udev(dev); static const char *searchpath[] = { FIRMWARE_PATH }; char loadpath[UTIL_PATH_SIZE]; char datapath[UTIL_PATH_SIZE]; char fwpath[UTIL_PATH_SIZE]; const char *firmware; FILE *fwfile = NULL; struct utsname kernel; struct stat statbuf; unsigned int i; int rc = EXIT_SUCCESS; firmware = udev_device_get_property_value(dev, "FIRMWARE"); if (firmware == NULL) { log_error("firmware parameter missing"); rc = EXIT_FAILURE; goto exit; } /* lookup firmware file */ uname(&kernel); for (i = 0; i < ELEMENTSOF(searchpath); i++) { strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; } strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); if (fwfile == NULL) { log_debug("did not find firmware file '%s'", firmware); rc = EXIT_FAILURE; /* * Do not cancel the request in the initrd, the real root might have * the firmware file and the 'coldplug' run in the real root will find * this pending request and fulfill or cancel it. * */ if (!in_initrd()) set_loading(udev, loadpath, "-1"); goto exit; } if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { if (!in_initrd()) set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; } if (!set_loading(udev, loadpath, "1")) goto exit; strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { log_error("error sending firmware '%s' to device", firmware); set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; }; set_loading(udev, loadpath, "0"); exit: if (fwfile) fclose(fwfile); return rc; }
static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev *udev = udev_device_get_udev(dev); static const char *searchpath[] = { FIRMWARE_PATH }; char fwencpath[UTIL_PATH_SIZE]; char misspath[UTIL_PATH_SIZE]; char loadpath[UTIL_PATH_SIZE]; char datapath[UTIL_PATH_SIZE]; char fwpath[UTIL_PATH_SIZE]; const char *firmware; FILE *fwfile = NULL; struct utsname kernel; struct stat statbuf; unsigned int i; int rc = EXIT_SUCCESS; firmware = udev_device_get_property_value(dev, "FIRMWARE"); if (firmware == NULL) { log_error("firmware parameter missing\n\n"); rc = EXIT_FAILURE; goto exit; } /* lookup firmware file */ uname(&kernel); for (i = 0; i < ELEMENTSOF(searchpath); i++) { util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; } util_path_encode(firmware, fwencpath, sizeof(fwencpath)); util_strscpyl(misspath, sizeof(misspath), "/run/udev/firmware-missing/", fwencpath, NULL); util_strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); if (fwfile == NULL) { int err; /* This link indicates the missing firmware file and the associated device */ log_debug("did not find firmware file '%s'\n", firmware); do { err = mkdir_parents(misspath, 0755); if (err != 0 && err != -ENOENT) break; err = symlink(udev_device_get_devpath(dev), misspath); if (err != 0) err = -errno; } while (err == -ENOENT); rc = EXIT_FAILURE; /* * Do not cancel the request in the initrd, the real root might have * the firmware file and the 'coldplug' run in the real root will find * this pending request and fulfill or cancel it. * */ if (!in_initrd()) set_loading(udev, loadpath, "-1"); goto exit; } if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { if (!in_initrd()) set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; } if (unlink(misspath) == 0) util_delete_path(udev, misspath); if (!set_loading(udev, loadpath, "1")) goto exit; util_strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { log_error("error sending firmware '%s' to device\n", firmware); set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; }; set_loading(udev, loadpath, "0"); exit: if (fwfile) fclose(fwfile); return rc; }