1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Remote Processor Framework Elf loader 4 * 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Copyright (C) 2011 Google, Inc. 7 * 8 * Ohad Ben-Cohen <ohad@wizery.com> 9 * Brian Swetland <swetland@google.com> 10 * Mark Grosen <mgrosen@ti.com> 11 * Fernando Guzman Lugo <fernando.lugo@ti.com> 12 * Suman Anna <s-anna@ti.com> 13 * Robert Tivy <rtivy@ti.com> 14 * Armando Uribe De Leon <x0095078@ti.com> 15 * Sjur Brændeland <sjur.brandeland@stericsson.com> 16 */ 17 18 #define pr_fmt(fmt) "%s: " fmt, __func__ 19 20 #include <linux/module.h> 21 #include <linux/firmware.h> 22 #include <linux/remoteproc.h> 23 #include <linux/elf.h> 24 25 #include "remoteproc_internal.h" 26 #include "remoteproc_elf_helpers.h" 27 28 /** 29 * rproc_elf_sanity_check() - Sanity Check for ELF32/ELF64 firmware image 30 * @rproc: the remote processor handle 31 * @fw: the ELF firmware image 32 * 33 * Make sure this fw image is sane (ie a correct ELF32/ELF64 file). 34 */ 35 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) 36 { 37 const char *name = rproc->firmware; 38 struct device *dev = &rproc->dev; 39 /* 40 * Elf files are beginning with the same structure. Thus, to simplify 41 * header parsing, we can use the elf32_hdr one for both elf64 and 42 * elf32. 43 */ 44 struct elf32_hdr *ehdr; 45 u32 elf_shdr_get_size; 46 u64 phoff, shoff; 47 char class; 48 u16 phnum; 49 50 if (!fw) { 51 dev_err(dev, "failed to load %s\n", name); 52 return -EINVAL; 53 } 54 55 if (fw->size < sizeof(struct elf32_hdr)) { 56 dev_err(dev, "Image is too small\n"); 57 return -EINVAL; 58 } 59 60 ehdr = (struct elf32_hdr *)fw->data; 61 62 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { 63 dev_err(dev, "Image is corrupted (bad magic)\n"); 64 return -EINVAL; 65 } 66 67 class = ehdr->e_ident[EI_CLASS]; 68 if (class != ELFCLASS32 && class != ELFCLASS64) { 69 dev_err(dev, "Unsupported class: %d\n", class); 70 return -EINVAL; 71 } 72 73 if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) { 74 dev_err(dev, "elf64 header is too small\n"); 75 return -EINVAL; 76 } 77 78 /* We assume the firmware has the same endianness as the host */ 79 # ifdef __LITTLE_ENDIAN 80 if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { 81 # else /* BIG ENDIAN */ 82 if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) { 83 # endif 84 dev_err(dev, "Unsupported firmware endianness\n"); 85 return -EINVAL; 86 } 87 88 phoff = elf_hdr_get_e_phoff(class, fw->data); 89 shoff = elf_hdr_get_e_shoff(class, fw->data); 90 phnum = elf_hdr_get_e_phnum(class, fw->data); 91 elf_shdr_get_size = elf_size_of_shdr(class); 92 93 if (fw->size < shoff + elf_shdr_get_size) { 94 dev_err(dev, "Image is too small\n"); 95 return -EINVAL; 96 } 97 98 if (phnum == 0) { 99 dev_err(dev, "No loadable segments\n"); 100 return -EINVAL; 101 } 102 103 if (phoff > fw->size) { 104 dev_err(dev, "Firmware size is too small\n"); 105 return -EINVAL; 106 } 107 108 dev_dbg(dev, "Firmware is an elf%d file\n", 109 class == ELFCLASS32 ? 32 : 64); 110 111 return 0; 112 } 113 EXPORT_SYMBOL(rproc_elf_sanity_check); 114 115 /** 116 * rproc_elf_get_boot_addr() - Get rproc's boot address. 117 * @rproc: the remote processor handle 118 * @fw: the ELF firmware image 119 * 120 * This function returns the entry point address of the ELF 121 * image. 122 * 123 * Note that the boot address is not a configurable property of all remote 124 * processors. Some will always boot at a specific hard-coded address. 125 */ 126 u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw) 127 { 128 return elf_hdr_get_e_entry(fw_elf_get_class(fw), fw->data); 129 } 130 EXPORT_SYMBOL(rproc_elf_get_boot_addr); 131 132 /** 133 * rproc_elf_load_segments() - load firmware segments to memory 134 * @rproc: remote processor which will be booted using these fw segments 135 * @fw: the ELF firmware image 136 * 137 * This function loads the firmware segments to memory, where the remote 138 * processor expects them. 139 * 140 * Some remote processors will expect their code and data to be placed 141 * in specific device addresses, and can't have them dynamically assigned. 142 * 143 * We currently support only those kind of remote processors, and expect 144 * the program header's paddr member to contain those addresses. We then go 145 * through the physically contiguous "carveout" memory regions which we 146 * allocated (and mapped) earlier on behalf of the remote processor, 147 * and "translate" device address to kernel addresses, so we can copy the 148 * segments where they are expected. 149 * 150 * Currently we only support remote processors that required carveout 151 * allocations and got them mapped onto their iommus. Some processors 152 * might be different: they might not have iommus, and would prefer to 153 * directly allocate memory for every segment/resource. This is not yet 154 * supported, though. 155 */ 156 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) 157 { 158 struct device *dev = &rproc->dev; 159 const void *ehdr, *phdr; 160 int i, ret = 0; 161 u16 phnum; 162 const u8 *elf_data = fw->data; 163 u8 class = fw_elf_get_class(fw); 164 u32 elf_phdr_get_size = elf_size_of_phdr(class); 165 166 ehdr = elf_data; 167 phnum = elf_hdr_get_e_phnum(class, ehdr); 168 phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr); 169 170 /* go through the available ELF segments */ 171 for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) { 172 u64 da = elf_phdr_get_p_paddr(class, phdr); 173 u64 memsz = elf_phdr_get_p_memsz(class, phdr); 174 u64 filesz = elf_phdr_get_p_filesz(class, phdr); 175 u64 offset = elf_phdr_get_p_offset(class, phdr); 176 u32 type = elf_phdr_get_p_type(class, phdr); 177 void *ptr; 178 bool is_iomem; 179 180 if (type != PT_LOAD) 181 continue; 182 183 dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n", 184 type, da, memsz, filesz); 185 186 if (filesz > memsz) { 187 dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n", 188 filesz, memsz); 189 ret = -EINVAL; 190 break; 191 } 192 193 if (offset + filesz > fw->size) { 194 dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n", 195 offset + filesz, fw->size); 196 ret = -EINVAL; 197 break; 198 } 199 200 if (!rproc_u64_fit_in_size_t(memsz)) { 201 dev_err(dev, "size (%llx) does not fit in size_t type\n", 202 memsz); 203 ret = -EOVERFLOW; 204 break; 205 } 206 207 /* grab the kernel address for this device address */ 208 ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem); 209 if (!ptr) { 210 dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da, 211 memsz); 212 ret = -EINVAL; 213 break; 214 } 215 216 /* put the segment where the remote processor expects it */ 217 if (filesz) { 218 if (is_iomem) 219 memcpy_fromio(ptr, (void __iomem *)(elf_data + offset), filesz); 220 else 221 memcpy(ptr, elf_data + offset, filesz); 222 } 223 224 /* 225 * Zero out remaining memory for this segment. 226 * 227 * This isn't strictly required since dma_alloc_coherent already 228 * did this for us. albeit harmless, we may consider removing 229 * this. 230 */ 231 if (memsz > filesz) { 232 if (is_iomem) 233 memset_io((void __iomem *)(ptr + filesz), 0, memsz - filesz); 234 else 235 memset(ptr + filesz, 0, memsz - filesz); 236 } 237 } 238 239 return ret; 240 } 241 EXPORT_SYMBOL(rproc_elf_load_segments); 242 243 static const void * 244 find_table(struct device *dev, const struct firmware *fw) 245 { 246 const void *shdr, *name_table_shdr; 247 int i; 248 const char *name_table; 249 struct resource_table *table = NULL; 250 const u8 *elf_data = (void *)fw->data; 251 u8 class = fw_elf_get_class(fw); 252 size_t fw_size = fw->size; 253 const void *ehdr = elf_data; 254 u16 shnum = elf_hdr_get_e_shnum(class, ehdr); 255 u32 elf_shdr_get_size = elf_size_of_shdr(class); 256 u16 shstrndx = elf_hdr_get_e_shstrndx(class, ehdr); 257 258 /* look for the resource table and handle it */ 259 /* First, get the section header according to the elf class */ 260 shdr = elf_data + elf_hdr_get_e_shoff(class, ehdr); 261 /* Compute name table section header entry in shdr array */ 262 name_table_shdr = shdr + (shstrndx * elf_shdr_get_size); 263 /* Finally, compute the name table section address in elf */ 264 name_table = elf_data + elf_shdr_get_sh_offset(class, name_table_shdr); 265 266 for (i = 0; i < shnum; i++, shdr += elf_shdr_get_size) { 267 u64 size = elf_shdr_get_sh_size(class, shdr); 268 u64 offset = elf_shdr_get_sh_offset(class, shdr); 269 u32 name = elf_shdr_get_sh_name(class, shdr); 270 271 if (strcmp(name_table + name, ".resource_table")) 272 continue; 273 274 table = (struct resource_table *)(elf_data + offset); 275 276 /* make sure we have the entire table */ 277 if (offset + size > fw_size || offset + size < size) { 278 dev_err(dev, "resource table truncated\n"); 279 return NULL; 280 } 281 282 /* make sure table has at least the header */ 283 if (sizeof(struct resource_table) > size) { 284 dev_err(dev, "header-less resource table\n"); 285 return NULL; 286 } 287 288 /* we don't support any version beyond the first */ 289 if (table->ver != 1) { 290 dev_err(dev, "unsupported fw ver: %d\n", table->ver); 291 return NULL; 292 } 293 294 /* make sure reserved bytes are zeroes */ 295 if (table->reserved[0] || table->reserved[1]) { 296 dev_err(dev, "non zero reserved bytes\n"); 297 return NULL; 298 } 299 300 /* make sure the offsets array isn't truncated */ 301 if (struct_size(table, offset, table->num) > size) { 302 dev_err(dev, "resource table incomplete\n"); 303 return NULL; 304 } 305 306 return shdr; 307 } 308 309 return NULL; 310 } 311 312 /** 313 * rproc_elf_load_rsc_table() - load the resource table 314 * @rproc: the rproc handle 315 * @fw: the ELF firmware image 316 * 317 * This function finds the resource table inside the remote processor's 318 * firmware, load it into the @cached_table and update @table_ptr. 319 * 320 * Return: 0 on success, negative errno on failure. 321 */ 322 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw) 323 { 324 const void *shdr; 325 struct device *dev = &rproc->dev; 326 struct resource_table *table = NULL; 327 const u8 *elf_data = fw->data; 328 size_t tablesz; 329 u8 class = fw_elf_get_class(fw); 330 u64 sh_offset; 331 332 shdr = find_table(dev, fw); 333 if (!shdr) 334 return -EINVAL; 335 336 sh_offset = elf_shdr_get_sh_offset(class, shdr); 337 table = (struct resource_table *)(elf_data + sh_offset); 338 tablesz = elf_shdr_get_sh_size(class, shdr); 339 340 /* 341 * Create a copy of the resource table. When a virtio device starts 342 * and calls vring_new_virtqueue() the address of the allocated vring 343 * will be stored in the cached_table. Before the device is started, 344 * cached_table will be copied into device memory. 345 */ 346 rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL); 347 if (!rproc->cached_table) 348 return -ENOMEM; 349 350 rproc->table_ptr = rproc->cached_table; 351 rproc->table_sz = tablesz; 352 353 return 0; 354 } 355 EXPORT_SYMBOL(rproc_elf_load_rsc_table); 356 357 /** 358 * rproc_elf_find_loaded_rsc_table() - find the loaded resource table 359 * @rproc: the rproc handle 360 * @fw: the ELF firmware image 361 * 362 * This function finds the location of the loaded resource table. Don't 363 * call this function if the table wasn't loaded yet - it's a bug if you do. 364 * 365 * Returns the pointer to the resource table if it is found or NULL otherwise. 366 * If the table wasn't loaded yet the result is unspecified. 367 */ 368 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, 369 const struct firmware *fw) 370 { 371 const void *shdr; 372 u64 sh_addr, sh_size; 373 u8 class = fw_elf_get_class(fw); 374 struct device *dev = &rproc->dev; 375 376 shdr = find_table(&rproc->dev, fw); 377 if (!shdr) 378 return NULL; 379 380 sh_addr = elf_shdr_get_sh_addr(class, shdr); 381 sh_size = elf_shdr_get_sh_size(class, shdr); 382 383 if (!rproc_u64_fit_in_size_t(sh_size)) { 384 dev_err(dev, "size (%llx) does not fit in size_t type\n", 385 sh_size); 386 return NULL; 387 } 388 389 return rproc_da_to_va(rproc, sh_addr, sh_size, NULL); 390 } 391 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table); 392