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 12*536fd818SRuss Weightdocumentation for firmware fallback. It also adds additional sysfs files 13*536fd818SRuss 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 6097730bbbSRuss Weight fwl = firmware_upload_register(sec->dev, sec->fw_name, &m10bmc_ops, sec); 6197730bbbSRuss Weight if (IS_ERR(fwl)) { 6297730bbbSRuss Weight dev_err(sec->dev, "Firmware Upload driver failed to start\n"); 6397730bbbSRuss Weight kfree(sec->fw_name); 6497730bbbSRuss Weight return PTR_ERR(fwl); 6597730bbbSRuss Weight } 6697730bbbSRuss Weight 6797730bbbSRuss Weight sec->fwl = fwl; 6897730bbbSRuss Weight return 0; 6997730bbbSRuss Weight } 7097730bbbSRuss Weight 7197730bbbSRuss Weight static int m10bmc_sec_remove(struct platform_device *pdev) 7297730bbbSRuss Weight { 7397730bbbSRuss Weight struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev); 7497730bbbSRuss Weight 7597730bbbSRuss Weight firmware_upload_unregister(sec->fwl); 7697730bbbSRuss Weight kfree(sec->fw_name); 7797730bbbSRuss Weight return 0; 7897730bbbSRuss Weight } 7997730bbbSRuss Weight 8097730bbbSRuss Weightfirmware_upload_register 8197730bbbSRuss Weight------------------------ 8297730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 8397730bbbSRuss Weight :identifiers: firmware_upload_register 8497730bbbSRuss Weight 8597730bbbSRuss Weightfirmware_upload_unregister 8697730bbbSRuss Weight-------------------------- 8797730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 8897730bbbSRuss Weight :identifiers: firmware_upload_unregister 8997730bbbSRuss Weight 9097730bbbSRuss WeightFirmware Upload Ops 9197730bbbSRuss Weight------------------- 9297730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 9397730bbbSRuss Weight :identifiers: fw_upload_ops 9497730bbbSRuss Weight 9597730bbbSRuss WeightFirmware Upload Progress Codes 9697730bbbSRuss Weight------------------------------ 97*536fd818SRuss WeightThe following progress codes are used internally by the firmware loader. 98*536fd818SRuss WeightCorresponding strings are reported through the status sysfs node that 99*536fd818SRuss Weightis described below and are documented in the ABI documentation. 10097730bbbSRuss Weight 10197730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h 10297730bbbSRuss Weight :identifiers: fw_upload_prog 10397730bbbSRuss Weight 10497730bbbSRuss WeightFirmware Upload Error Codes 10597730bbbSRuss Weight--------------------------- 10697730bbbSRuss WeightThe following error codes may be returned by the driver ops in case of 10797730bbbSRuss Weightfailure: 10897730bbbSRuss Weight 10997730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 11097730bbbSRuss Weight :identifiers: fw_upload_err 111*536fd818SRuss Weight 112*536fd818SRuss WeightSysfs Attributes 113*536fd818SRuss Weight================ 114*536fd818SRuss Weight 115*536fd818SRuss WeightIn addition to the *loading* and *data* sysfs files, there are additional 116*536fd818SRuss Weightsysfs files to monitor the status of the data transfer to the target 117*536fd818SRuss Weightdevice and to determine the final pass/fail status of the transfer. 118*536fd818SRuss WeightDepending on the device and the size of the firmware image, a firmware 119*536fd818SRuss Weightupdate could take milliseconds or minutes. 120*536fd818SRuss Weight 121*536fd818SRuss WeightThe additional sysfs files are: 122*536fd818SRuss Weight 123*536fd818SRuss Weight* status - provides an indication of the progress of a firmware update 124*536fd818SRuss Weight* error - provides error information for a failed firmware update 125*536fd818SRuss Weight* remaining_size - tracks the data transfer portion of an update 126*536fd818SRuss Weight* cancel - echo 1 to this file to cancel the update 127