197730bbbSRuss Weight.. SPDX-License-Identifier: GPL-2.0 297730bbbSRuss Weight 397730bbbSRuss Weight=================== 497730bbbSRuss WeightFirmware Upload API 597730bbbSRuss Weight=================== 697730bbbSRuss Weight 797730bbbSRuss WeightA device driver that registers with the firmware loader will expose 897730bbbSRuss Weightpersistent sysfs nodes to enable users to initiate firmware updates for 997730bbbSRuss Weightthat device. It is the responsibility of the device driver and/or the 1097730bbbSRuss Weightdevice itself to perform any validation on the data received. Firmware 1197730bbbSRuss Weightupload uses the same *loading* and *data* sysfs files described in the 12536fd818SRuss Weightdocumentation for firmware fallback. It also adds additional sysfs files 13536fd818SRuss Weightto provide status on the transfer of the firmware image to the device. 1497730bbbSRuss Weight 1597730bbbSRuss WeightRegister for firmware upload 1697730bbbSRuss Weight============================ 1797730bbbSRuss Weight 1897730bbbSRuss WeightA device driver registers for firmware upload by calling 1997730bbbSRuss Weightfirmware_upload_register(). Among the parameter list is a name to 2097730bbbSRuss Weightidentify the device under /sys/class/firmware. A user may initiate a 2197730bbbSRuss Weightfirmware upload by echoing a 1 to the *loading* sysfs file for the target 2297730bbbSRuss Weightdevice. Next, the user writes the firmware image to the *data* sysfs 2397730bbbSRuss Weightfile. After writing the firmware data, the user echos 0 to the *loading* 2497730bbbSRuss Weightsysfs file to signal completion. Echoing 0 to *loading* also triggers the 2597730bbbSRuss Weighttransfer of the firmware to the lower-lever device driver in the context 2697730bbbSRuss Weightof a kernel worker thread. 2797730bbbSRuss Weight 2897730bbbSRuss WeightTo use the firmware upload API, write a driver that implements a set of 2997730bbbSRuss Weightops. The probe function calls firmware_upload_register() and the remove 3097730bbbSRuss Weightfunction calls firmware_upload_unregister() such as:: 3197730bbbSRuss Weight 3297730bbbSRuss Weight static const struct fw_upload_ops m10bmc_ops = { 3397730bbbSRuss Weight .prepare = m10bmc_sec_prepare, 3497730bbbSRuss Weight .write = m10bmc_sec_write, 3597730bbbSRuss Weight .poll_complete = m10bmc_sec_poll_complete, 3697730bbbSRuss Weight .cancel = m10bmc_sec_cancel, 3797730bbbSRuss Weight .cleanup = m10bmc_sec_cleanup, 3897730bbbSRuss Weight }; 3997730bbbSRuss Weight 4097730bbbSRuss Weight static int m10bmc_sec_probe(struct platform_device *pdev) 4197730bbbSRuss Weight { 4297730bbbSRuss Weight const char *fw_name, *truncate; 4397730bbbSRuss Weight struct m10bmc_sec *sec; 4497730bbbSRuss Weight struct fw_upload *fwl; 4597730bbbSRuss Weight unsigned int len; 4697730bbbSRuss Weight 4797730bbbSRuss Weight sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL); 4897730bbbSRuss Weight if (!sec) 4997730bbbSRuss Weight return -ENOMEM; 5097730bbbSRuss Weight 5197730bbbSRuss Weight sec->dev = &pdev->dev; 5297730bbbSRuss Weight sec->m10bmc = dev_get_drvdata(pdev->dev.parent); 5397730bbbSRuss Weight dev_set_drvdata(&pdev->dev, sec); 5497730bbbSRuss Weight 5597730bbbSRuss Weight fw_name = dev_name(sec->dev); 5697730bbbSRuss Weight truncate = strstr(fw_name, ".auto"); 5797730bbbSRuss Weight len = (truncate) ? truncate - fw_name : strlen(fw_name); 5897730bbbSRuss Weight sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL); 5997730bbbSRuss Weight 60*61f21988SConor Dooley fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name, 61*61f21988SConor Dooley &m10bmc_ops, sec); 6297730bbbSRuss Weight if (IS_ERR(fwl)) { 6397730bbbSRuss Weight dev_err(sec->dev, "Firmware Upload driver failed to start\n"); 6497730bbbSRuss Weight kfree(sec->fw_name); 6597730bbbSRuss Weight return PTR_ERR(fwl); 6697730bbbSRuss Weight } 6797730bbbSRuss Weight 6897730bbbSRuss Weight sec->fwl = fwl; 6997730bbbSRuss Weight return 0; 7097730bbbSRuss Weight } 7197730bbbSRuss Weight 7297730bbbSRuss Weight static int m10bmc_sec_remove(struct platform_device *pdev) 7397730bbbSRuss Weight { 7497730bbbSRuss Weight struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev); 7597730bbbSRuss Weight 7697730bbbSRuss Weight firmware_upload_unregister(sec->fwl); 7797730bbbSRuss Weight kfree(sec->fw_name); 7897730bbbSRuss Weight return 0; 7997730bbbSRuss Weight } 8097730bbbSRuss Weight 8197730bbbSRuss Weightfirmware_upload_register 8297730bbbSRuss Weight------------------------ 8397730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 8497730bbbSRuss Weight :identifiers: firmware_upload_register 8597730bbbSRuss Weight 8697730bbbSRuss Weightfirmware_upload_unregister 8797730bbbSRuss Weight-------------------------- 8897730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 8997730bbbSRuss Weight :identifiers: firmware_upload_unregister 9097730bbbSRuss Weight 9197730bbbSRuss WeightFirmware Upload Ops 9297730bbbSRuss Weight------------------- 9397730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 9497730bbbSRuss Weight :identifiers: fw_upload_ops 9597730bbbSRuss Weight 9697730bbbSRuss WeightFirmware Upload Progress Codes 9797730bbbSRuss Weight------------------------------ 98536fd818SRuss WeightThe following progress codes are used internally by the firmware loader. 99536fd818SRuss WeightCorresponding strings are reported through the status sysfs node that 100536fd818SRuss Weightis described below and are documented in the ABI documentation. 10197730bbbSRuss Weight 10297730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h 10397730bbbSRuss Weight :identifiers: fw_upload_prog 10497730bbbSRuss Weight 10597730bbbSRuss WeightFirmware Upload Error Codes 10697730bbbSRuss Weight--------------------------- 10797730bbbSRuss WeightThe following error codes may be returned by the driver ops in case of 10897730bbbSRuss Weightfailure: 10997730bbbSRuss Weight 11097730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 11197730bbbSRuss Weight :identifiers: fw_upload_err 112536fd818SRuss Weight 113536fd818SRuss WeightSysfs Attributes 114536fd818SRuss Weight================ 115536fd818SRuss Weight 116536fd818SRuss WeightIn addition to the *loading* and *data* sysfs files, there are additional 117536fd818SRuss Weightsysfs files to monitor the status of the data transfer to the target 118536fd818SRuss Weightdevice and to determine the final pass/fail status of the transfer. 119536fd818SRuss WeightDepending on the device and the size of the firmware image, a firmware 120536fd818SRuss Weightupdate could take milliseconds or minutes. 121536fd818SRuss Weight 122536fd818SRuss WeightThe additional sysfs files are: 123536fd818SRuss Weight 124536fd818SRuss Weight* status - provides an indication of the progress of a firmware update 125536fd818SRuss Weight* error - provides error information for a failed firmware update 126536fd818SRuss Weight* remaining_size - tracks the data transfer portion of an update 127536fd818SRuss Weight* cancel - echo 1 to this file to cancel the update 128