Bin Meng | 3d45f2d | 2019-07-18 00:33:52 -0700 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0+ |
| 2 | .. Copyright (C) 2018-2019 Intel Corporation <www.intel.com> |
| 3 | |
| 4 | File System Firmware Loader |
| 5 | =========================== |
| 6 | |
| 7 | This is file system firmware loader for U-Boot framework, which has very close |
| 8 | to some Linux Firmware API. For the details of Linux Firmware API, you can refer |
| 9 | to https://01.org/linuxgraphics/gfx-docs/drm/driver-api/firmware/index.html. |
| 10 | |
| 11 | File system firmware loader can be used to load whatever(firmware, image, |
| 12 | and binary) from the storage device in file system format into target location |
| 13 | such as memory, then consumer driver such as FPGA driver can program FPGA image |
| 14 | from the target location into FPGA. |
| 15 | |
| 16 | To enable firmware loader, CONFIG_FS_LOADER need to be set at |
| 17 | <board_name>_defconfig such as "CONFIG_FS_LOADER=y". |
| 18 | |
| 19 | Firmware Loader API core features |
| 20 | --------------------------------- |
| 21 | |
| 22 | Firmware storage device described in device tree source |
| 23 | ------------------------------------------------------- |
| 24 | For passing data like storage device phandle and partition where the |
| 25 | firmware loading from to the firmware loader driver, those data could be |
| 26 | defined in fs-loader node as shown in below: |
| 27 | |
| 28 | Example for block device:: |
| 29 | |
| 30 | fs_loader0: fs-loader { |
Simon Glass | b9a1a05 | 2023-02-13 08:56:36 -0700 | [diff] [blame^] | 31 | bootph-all; |
Bin Meng | 3d45f2d | 2019-07-18 00:33:52 -0700 | [diff] [blame] | 32 | compatible = "u-boot,fs-loader"; |
| 33 | phandlepart = <&mmc 1>; |
| 34 | }; |
| 35 | |
| 36 | <&mmc 1> means block storage device pointer and its partition. |
| 37 | |
| 38 | Above example is a description for block storage, but for UBI storage |
| 39 | device, it can be described in FDT as shown in below: |
| 40 | |
| 41 | Example for ubi:: |
| 42 | |
| 43 | fs_loader1: fs-loader { |
Simon Glass | b9a1a05 | 2023-02-13 08:56:36 -0700 | [diff] [blame^] | 44 | bootph-all; |
Bin Meng | 3d45f2d | 2019-07-18 00:33:52 -0700 | [diff] [blame] | 45 | compatible = "u-boot,fs-loader"; |
| 46 | mtdpart = "UBI", |
| 47 | ubivol = "ubi0"; |
| 48 | }; |
| 49 | |
| 50 | Then, firmware-loader property can be added with any device node, which |
| 51 | driver would use the firmware loader for loading. |
| 52 | |
| 53 | The value of the firmware-loader property should be set with phandle |
| 54 | of the fs-loader node. For example:: |
| 55 | |
| 56 | firmware-loader = <&fs_loader0>; |
| 57 | |
| 58 | If there are majority of devices using the same fs-loader node, then |
| 59 | firmware-loader property can be added under /chosen node instead of |
| 60 | adding to each of device node. |
| 61 | |
| 62 | For example:: |
| 63 | |
| 64 | /{ |
| 65 | chosen { |
| 66 | firmware-loader = <&fs_loader0>; |
| 67 | }; |
| 68 | }; |
| 69 | |
| 70 | In each respective driver of devices using firmware loader, the firmware |
| 71 | loaded instance should be created by DT phandle. |
| 72 | |
| 73 | For example of getting DT phandle from /chosen and creating instance: |
| 74 | |
| 75 | .. code-block:: c |
| 76 | |
| 77 | chosen_node = ofnode_path("/chosen"); |
| 78 | if (!ofnode_valid(chosen_node)) { |
| 79 | debug("/chosen node was not found.\n"); |
| 80 | return -ENOENT; |
| 81 | } |
| 82 | |
| 83 | phandle_p = ofnode_get_property(chosen_node, "firmware-loader", &size); |
| 84 | if (!phandle_p) { |
| 85 | debug("firmware-loader property was not found.\n"); |
| 86 | return -ENOENT; |
| 87 | } |
| 88 | |
| 89 | phandle = fdt32_to_cpu(*phandle_p); |
| 90 | ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER, |
| 91 | phandle, &dev); |
| 92 | if (ret) |
| 93 | return ret; |
| 94 | |
| 95 | Firmware loader driver is also designed to support U-boot environment |
| 96 | variables, so all these data from FDT can be overwritten |
| 97 | through the U-boot environment variable during run time. |
| 98 | |
| 99 | For examples: |
| 100 | |
| 101 | storage_interface: |
| 102 | Storage interface, it can be "mmc", "usb", "sata" or "ubi". |
| 103 | fw_dev_part: |
| 104 | Block device number and its partition, it can be "0:1". |
| 105 | fw_ubi_mtdpart: |
| 106 | UBI device mtd partition, it can be "UBI". |
| 107 | fw_ubi_volume: |
| 108 | UBI volume, it can be "ubi0". |
| 109 | |
| 110 | When above environment variables are set, environment values would be |
| 111 | used instead of data from FDT. |
| 112 | The benefit of this design allows user to change storage attribute data |
| 113 | at run time through U-boot console and saving the setting as default |
| 114 | environment values in the storage for the next power cycle, so no |
| 115 | compilation is required for both driver and FDT. |
| 116 | |
| 117 | File system firmware Loader API |
| 118 | ------------------------------- |
| 119 | |
| 120 | .. code-block:: c |
| 121 | |
| 122 | int request_firmware_into_buf(struct udevice *dev, |
| 123 | const char *name, |
| 124 | void *buf, size_t size, u32 offset) |
| 125 | |
| 126 | Load firmware into a previously allocated buffer |
| 127 | |
| 128 | Parameters: |
| 129 | |
| 130 | * struct udevice \*dev: An instance of a driver |
| 131 | * const char \*name: name of firmware file |
| 132 | * void \*buf: address of buffer to load firmware into |
| 133 | * size_t size: size of buffer |
| 134 | * u32 offset: offset of a file for start reading into buffer |
| 135 | |
| 136 | Returns: |
| 137 | size of total read |
| 138 | -ve when error |
| 139 | |
| 140 | Description: |
| 141 | The firmware is loaded directly into the buffer pointed to by buf |
| 142 | |
| 143 | Example of calling request_firmware_into_buf API after creating firmware loader |
| 144 | instance: |
| 145 | |
| 146 | .. code-block:: c |
| 147 | |
| 148 | ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER, |
| 149 | phandle, &dev); |
| 150 | if (ret) |
| 151 | return ret; |
| 152 | |
| 153 | request_firmware_into_buf(dev, filename, buffer_location, buffer_size, |
| 154 | offset_ofreading); |