1*97730bbbSRuss Weight.. SPDX-License-Identifier: GPL-2.0 2*97730bbbSRuss Weight 3*97730bbbSRuss Weight=================== 4*97730bbbSRuss WeightFirmware Upload API 5*97730bbbSRuss Weight=================== 6*97730bbbSRuss Weight 7*97730bbbSRuss WeightA device driver that registers with the firmware loader will expose 8*97730bbbSRuss Weightpersistent sysfs nodes to enable users to initiate firmware updates for 9*97730bbbSRuss Weightthat device. It is the responsibility of the device driver and/or the 10*97730bbbSRuss Weightdevice itself to perform any validation on the data received. Firmware 11*97730bbbSRuss Weightupload uses the same *loading* and *data* sysfs files described in the 12*97730bbbSRuss Weightdocumentation for firmware fallback. 13*97730bbbSRuss Weight 14*97730bbbSRuss WeightRegister for firmware upload 15*97730bbbSRuss Weight============================ 16*97730bbbSRuss Weight 17*97730bbbSRuss WeightA device driver registers for firmware upload by calling 18*97730bbbSRuss Weightfirmware_upload_register(). Among the parameter list is a name to 19*97730bbbSRuss Weightidentify the device under /sys/class/firmware. A user may initiate a 20*97730bbbSRuss Weightfirmware upload by echoing a 1 to the *loading* sysfs file for the target 21*97730bbbSRuss Weightdevice. Next, the user writes the firmware image to the *data* sysfs 22*97730bbbSRuss Weightfile. After writing the firmware data, the user echos 0 to the *loading* 23*97730bbbSRuss Weightsysfs file to signal completion. Echoing 0 to *loading* also triggers the 24*97730bbbSRuss Weighttransfer of the firmware to the lower-lever device driver in the context 25*97730bbbSRuss Weightof a kernel worker thread. 26*97730bbbSRuss Weight 27*97730bbbSRuss WeightTo use the firmware upload API, write a driver that implements a set of 28*97730bbbSRuss Weightops. The probe function calls firmware_upload_register() and the remove 29*97730bbbSRuss Weightfunction calls firmware_upload_unregister() such as:: 30*97730bbbSRuss Weight 31*97730bbbSRuss Weight static const struct fw_upload_ops m10bmc_ops = { 32*97730bbbSRuss Weight .prepare = m10bmc_sec_prepare, 33*97730bbbSRuss Weight .write = m10bmc_sec_write, 34*97730bbbSRuss Weight .poll_complete = m10bmc_sec_poll_complete, 35*97730bbbSRuss Weight .cancel = m10bmc_sec_cancel, 36*97730bbbSRuss Weight .cleanup = m10bmc_sec_cleanup, 37*97730bbbSRuss Weight }; 38*97730bbbSRuss Weight 39*97730bbbSRuss Weight static int m10bmc_sec_probe(struct platform_device *pdev) 40*97730bbbSRuss Weight { 41*97730bbbSRuss Weight const char *fw_name, *truncate; 42*97730bbbSRuss Weight struct m10bmc_sec *sec; 43*97730bbbSRuss Weight struct fw_upload *fwl; 44*97730bbbSRuss Weight unsigned int len; 45*97730bbbSRuss Weight 46*97730bbbSRuss Weight sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL); 47*97730bbbSRuss Weight if (!sec) 48*97730bbbSRuss Weight return -ENOMEM; 49*97730bbbSRuss Weight 50*97730bbbSRuss Weight sec->dev = &pdev->dev; 51*97730bbbSRuss Weight sec->m10bmc = dev_get_drvdata(pdev->dev.parent); 52*97730bbbSRuss Weight dev_set_drvdata(&pdev->dev, sec); 53*97730bbbSRuss Weight 54*97730bbbSRuss Weight fw_name = dev_name(sec->dev); 55*97730bbbSRuss Weight truncate = strstr(fw_name, ".auto"); 56*97730bbbSRuss Weight len = (truncate) ? truncate - fw_name : strlen(fw_name); 57*97730bbbSRuss Weight sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL); 58*97730bbbSRuss Weight 59*97730bbbSRuss Weight fwl = firmware_upload_register(sec->dev, sec->fw_name, &m10bmc_ops, sec); 60*97730bbbSRuss Weight if (IS_ERR(fwl)) { 61*97730bbbSRuss Weight dev_err(sec->dev, "Firmware Upload driver failed to start\n"); 62*97730bbbSRuss Weight kfree(sec->fw_name); 63*97730bbbSRuss Weight return PTR_ERR(fwl); 64*97730bbbSRuss Weight } 65*97730bbbSRuss Weight 66*97730bbbSRuss Weight sec->fwl = fwl; 67*97730bbbSRuss Weight return 0; 68*97730bbbSRuss Weight } 69*97730bbbSRuss Weight 70*97730bbbSRuss Weight static int m10bmc_sec_remove(struct platform_device *pdev) 71*97730bbbSRuss Weight { 72*97730bbbSRuss Weight struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev); 73*97730bbbSRuss Weight 74*97730bbbSRuss Weight firmware_upload_unregister(sec->fwl); 75*97730bbbSRuss Weight kfree(sec->fw_name); 76*97730bbbSRuss Weight return 0; 77*97730bbbSRuss Weight } 78*97730bbbSRuss Weight 79*97730bbbSRuss Weightfirmware_upload_register 80*97730bbbSRuss Weight------------------------ 81*97730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 82*97730bbbSRuss Weight :identifiers: firmware_upload_register 83*97730bbbSRuss Weight 84*97730bbbSRuss Weightfirmware_upload_unregister 85*97730bbbSRuss Weight-------------------------- 86*97730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c 87*97730bbbSRuss Weight :identifiers: firmware_upload_unregister 88*97730bbbSRuss Weight 89*97730bbbSRuss WeightFirmware Upload Ops 90*97730bbbSRuss Weight------------------- 91*97730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 92*97730bbbSRuss Weight :identifiers: fw_upload_ops 93*97730bbbSRuss Weight 94*97730bbbSRuss WeightFirmware Upload Progress Codes 95*97730bbbSRuss Weight------------------------------ 96*97730bbbSRuss WeightThe following progress codes are used internally by the firmware loader: 97*97730bbbSRuss Weight 98*97730bbbSRuss Weight.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h 99*97730bbbSRuss Weight :identifiers: fw_upload_prog 100*97730bbbSRuss Weight 101*97730bbbSRuss WeightFirmware Upload Error Codes 102*97730bbbSRuss Weight--------------------------- 103*97730bbbSRuss WeightThe following error codes may be returned by the driver ops in case of 104*97730bbbSRuss Weightfailure: 105*97730bbbSRuss Weight 106*97730bbbSRuss Weight.. kernel-doc:: include/linux/firmware.h 107*97730bbbSRuss Weight :identifiers: fw_upload_err 108