1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018 Intel Corporation <www.intel.com> 4 * 5 */ 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <blk.h> 10 #include <fs.h> 11 #include <fs_loader.h> 12 #include <linux/string.h> 13 #include <mapmem.h> 14 #include <malloc.h> 15 #include <spl.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 struct firmware_priv { 20 const char *name; /* Filename */ 21 u32 offset; /* Offset of reading a file */ 22 }; 23 24 #ifdef CONFIG_CMD_UBIFS 25 static int mount_ubifs(char *mtdpart, char *ubivol) 26 { 27 int ret = ubi_part(mtdpart, NULL); 28 29 if (ret) { 30 debug("Cannot find mtd partition %s\n", mtdpart); 31 return ret; 32 } 33 34 return cmd_ubifs_mount(ubivol); 35 } 36 37 static int umount_ubifs(void) 38 { 39 return cmd_ubifs_umount(); 40 } 41 #else 42 static int mount_ubifs(char *mtdpart, char *ubivol) 43 { 44 debug("Error: Cannot load image: no UBIFS support\n"); 45 return -ENOSYS; 46 } 47 #endif 48 49 static int select_fs_dev(struct device_platdata *plat) 50 { 51 int ret; 52 53 if (plat->phandlepart.phandle) { 54 ofnode node; 55 56 node = ofnode_get_by_phandle(plat->phandlepart.phandle); 57 58 int of_offset = ofnode_to_offset(node); 59 60 struct udevice *dev; 61 62 ret = device_get_global_by_of_offset(of_offset, &dev); 63 if (!ret) { 64 struct blk_desc *desc = blk_get_by_device(dev); 65 if (desc) { 66 ret = fs_set_blk_dev_with_part(desc, 67 plat->phandlepart.partition); 68 } else { 69 debug("%s: No device found\n", __func__); 70 return -ENODEV; 71 } 72 } 73 } else if (plat->mtdpart && plat->ubivol) { 74 ret = mount_ubifs(plat->mtdpart, plat->ubivol); 75 if (ret) 76 return ret; 77 78 ret = fs_set_blk_dev("ubi", NULL, FS_TYPE_UBIFS); 79 } else { 80 debug("Error: unsupported storage device.\n"); 81 return -ENODEV; 82 } 83 84 if (ret) 85 debug("Error: could not access storage.\n"); 86 87 return ret; 88 } 89 90 /** 91 * _request_firmware_prepare - Prepare firmware struct. 92 * 93 * @name: Name of firmware file. 94 * @dbuf: Address of buffer to load firmware into. 95 * @size: Size of buffer. 96 * @offset: Offset of a file for start reading into buffer. 97 * @firmwarep: Pointer to pointer to firmware image. 98 * 99 * Return: Negative value if fail, 0 for successful. 100 */ 101 static int _request_firmware_prepare(const char *name, void *dbuf, 102 size_t size, u32 offset, 103 struct firmware **firmwarep) 104 { 105 if (!name || name[0] == '\0') 106 return -EINVAL; 107 108 /* No memory allocation is required if *firmwarep is allocated */ 109 if (!(*firmwarep)) { 110 (*firmwarep) = calloc(1, sizeof(struct firmware)); 111 if (!(*firmwarep)) 112 return -ENOMEM; 113 114 (*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv)); 115 if (!(*firmwarep)->priv) { 116 free(*firmwarep); 117 return -ENOMEM; 118 } 119 } else if (!(*firmwarep)->priv) { 120 (*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv)); 121 if (!(*firmwarep)->priv) { 122 free(*firmwarep); 123 return -ENOMEM; 124 } 125 } 126 127 ((struct firmware_priv *)((*firmwarep)->priv))->name = name; 128 ((struct firmware_priv *)((*firmwarep)->priv))->offset = offset; 129 (*firmwarep)->data = dbuf; 130 (*firmwarep)->size = size; 131 132 return 0; 133 } 134 135 /** 136 * release_firmware - Release the resource associated with a firmware image 137 * @firmware: Firmware resource to release 138 */ 139 void release_firmware(struct firmware *firmware) 140 { 141 if (firmware) { 142 if (firmware->priv) { 143 free(firmware->priv); 144 firmware->priv = NULL; 145 } 146 free(firmware); 147 } 148 } 149 150 /** 151 * fw_get_filesystem_firmware - load firmware into an allocated buffer. 152 * @plat: Platform data such as storage and partition firmware loading from. 153 * @firmware: pointer to firmware image. 154 * 155 * Return: Size of total read, negative value when error. 156 */ 157 static int fw_get_filesystem_firmware(struct device_platdata *plat, 158 struct firmware *firmware) 159 { 160 struct firmware_priv *fw_priv = NULL; 161 loff_t actread; 162 char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume; 163 int ret; 164 165 storage_interface = env_get("storage_interface"); 166 dev_part = env_get("fw_dev_part"); 167 ubi_mtdpart = env_get("fw_ubi_mtdpart"); 168 ubi_volume = env_get("fw_ubi_volume"); 169 170 if (storage_interface && dev_part) { 171 ret = fs_set_blk_dev(storage_interface, dev_part, FS_TYPE_ANY); 172 } else if (storage_interface && ubi_mtdpart && ubi_volume) { 173 ret = mount_ubifs(ubi_mtdpart, ubi_volume); 174 if (ret) 175 return ret; 176 177 if (!strcmp("ubi", storage_interface)) 178 ret = fs_set_blk_dev(storage_interface, NULL, 179 FS_TYPE_UBIFS); 180 else 181 ret = -ENODEV; 182 } else { 183 ret = select_fs_dev(plat); 184 } 185 186 if (ret) 187 goto out; 188 189 fw_priv = firmware->priv; 190 191 ret = fs_read(fw_priv->name, (ulong)map_to_sysmem(firmware->data), 192 fw_priv->offset, firmware->size, &actread); 193 if (ret) { 194 debug("Error: %d Failed to read %s from flash %lld != %d.\n", 195 ret, fw_priv->name, actread, firmware->size); 196 } else { 197 ret = actread; 198 } 199 200 out: 201 #ifdef CONFIG_CMD_UBIFS 202 umount_ubifs(); 203 #endif 204 return ret; 205 } 206 207 /** 208 * request_firmware_into_buf - Load firmware into a previously allocated buffer. 209 * @plat: Platform data such as storage and partition firmware loading from. 210 * @name: Name of firmware file. 211 * @buf: Address of buffer to load firmware into. 212 * @size: Size of buffer. 213 * @offset: Offset of a file for start reading into buffer. 214 * @firmwarep: Pointer to firmware image. 215 * 216 * The firmware is loaded directly into the buffer pointed to by @buf and 217 * the @firmwarep data member is pointed at @buf. 218 * 219 * Return: Size of total read, negative value when error. 220 */ 221 int request_firmware_into_buf(struct device_platdata *plat, 222 const char *name, 223 void *buf, size_t size, u32 offset, 224 struct firmware **firmwarep) 225 { 226 int ret; 227 228 if (!plat) 229 return -EINVAL; 230 231 ret = _request_firmware_prepare(name, buf, size, offset, firmwarep); 232 if (ret < 0) /* error */ 233 return ret; 234 235 ret = fw_get_filesystem_firmware(plat, *firmwarep); 236 237 return ret; 238 } 239 240 static int fs_loader_ofdata_to_platdata(struct udevice *dev) 241 { 242 const char *fs_loader_path; 243 u32 phandlepart[2]; 244 245 fs_loader_path = ofnode_get_chosen_prop("firmware-loader"); 246 247 if (fs_loader_path) { 248 ofnode fs_loader_node; 249 250 fs_loader_node = ofnode_path(fs_loader_path); 251 if (ofnode_valid(fs_loader_node)) { 252 struct device_platdata *plat; 253 plat = dev->platdata; 254 255 if (!ofnode_read_u32_array(fs_loader_node, 256 "phandlepart", 257 phandlepart, 2)) { 258 plat->phandlepart.phandle = phandlepart[0]; 259 plat->phandlepart.partition = phandlepart[1]; 260 } 261 262 plat->mtdpart = (char *)ofnode_read_string( 263 fs_loader_node, "mtdpart"); 264 265 plat->ubivol = (char *)ofnode_read_string( 266 fs_loader_node, "ubivol"); 267 } 268 } 269 270 return 0; 271 } 272 273 static int fs_loader_probe(struct udevice *dev) 274 { 275 return 0; 276 }; 277 278 static const struct udevice_id fs_loader_ids[] = { 279 { .compatible = "u-boot,fs-loader"}, 280 { } 281 }; 282 283 U_BOOT_DRIVER(fs_loader) = { 284 .name = "fs-loader", 285 .id = UCLASS_FS_FIRMWARE_LOADER, 286 .of_match = fs_loader_ids, 287 .probe = fs_loader_probe, 288 .ofdata_to_platdata = fs_loader_ofdata_to_platdata, 289 .platdata_auto_alloc_size = sizeof(struct device_platdata), 290 }; 291 292 UCLASS_DRIVER(fs_loader) = { 293 .id = UCLASS_FS_FIRMWARE_LOADER, 294 .name = "fs-loader", 295 }; 296