1 /* 2 * Copyright (c) 2014, Mentor Graphics Corporation 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #ifndef ELF_LOADER_H_ 9 #define ELF_LOADER_H_ 10 11 #include <openamp/remoteproc.h> 12 #include <openamp/remoteproc_loader.h> 13 14 #if defined __cplusplus 15 extern "C" { 16 #endif 17 18 /* ELF32 base types - 32-bit. */ 19 typedef uint32_t Elf32_Addr; 20 typedef uint16_t Elf32_Half; 21 typedef uint32_t Elf32_Off; 22 typedef int32_t Elf32_Sword; 23 typedef uint32_t Elf32_Word; 24 25 /* ELF64 base types - 64-bit. */ 26 typedef uint64_t Elf64_Addr; 27 typedef uint16_t Elf64_Half; 28 typedef uint64_t Elf64_Off; 29 typedef int32_t Elf64_Sword; 30 typedef uint32_t Elf64_Word; 31 typedef uint64_t Elf64_Xword; 32 typedef int64_t Elf64_Sxword; 33 34 /* Size of ELF identifier field in the ELF file header. */ 35 #define EI_NIDENT 16 36 37 /* ELF32 file header */ 38 typedef struct { 39 unsigned char e_ident[EI_NIDENT]; 40 Elf32_Half e_type; 41 Elf32_Half e_machine; 42 Elf32_Word e_version; 43 Elf32_Addr e_entry; 44 Elf32_Off e_phoff; 45 Elf32_Off e_shoff; 46 Elf32_Word e_flags; 47 Elf32_Half e_ehsize; 48 Elf32_Half e_phentsize; 49 Elf32_Half e_phnum; 50 Elf32_Half e_shentsize; 51 Elf32_Half e_shnum; 52 Elf32_Half e_shstrndx; 53 } Elf32_Ehdr; 54 55 /* ELF64 file header */ 56 typedef struct { 57 unsigned char e_ident[EI_NIDENT]; 58 Elf64_Half e_type; 59 Elf64_Half e_machine; 60 Elf64_Word e_version; 61 Elf64_Addr e_entry; 62 Elf64_Off e_phoff; 63 Elf64_Off e_shoff; 64 Elf64_Word e_flags; 65 Elf64_Half e_ehsize; 66 Elf64_Half e_phentsize; 67 Elf64_Half e_phnum; 68 Elf64_Half e_shentsize; 69 Elf64_Half e_shnum; 70 Elf64_Half e_shstrndx; 71 } Elf64_Ehdr; 72 73 /* e_ident */ 74 #define ET_NONE 0 75 #define ET_REL 1 /* Re-locatable file */ 76 #define ET_EXEC 2 /* Executable file */ 77 #define ET_DYN 3 /* Shared object file */ 78 #define ET_CORE 4 /* Core file */ 79 #define ET_LOOS 0xfe00 /* Operating system-specific */ 80 #define ET_HIOS 0xfeff /* Operating system-specific */ 81 #define ET_LOPROC 0xff00 /* remote_proc-specific */ 82 #define ET_HIPROC 0xffff /* remote_proc-specific */ 83 84 /* e_machine */ 85 #define EM_ARM 40 /* ARM/Thumb Architecture */ 86 87 /* e_version */ 88 #define EV_CURRENT 1 /* Current version */ 89 90 /* e_ident[] Identification Indexes */ 91 #define EI_MAG0 0 /* File identification */ 92 #define EI_MAG1 1 /* File identification */ 93 #define EI_MAG2 2 /* File identification */ 94 #define EI_MAG3 3 /* File identification */ 95 #define EI_CLASS 4 /* File class */ 96 #define EI_DATA 5 /* Data encoding */ 97 #define EI_VERSION 6 /* File version */ 98 #define EI_OSABI 7 /* Operating system/ABI identification */ 99 #define EI_ABIVERSION 8 /* ABI version */ 100 #define EI_PAD 9 /* Start of padding bytes */ 101 #define EI_NIDENT 16 /* Size of e_ident[] */ 102 103 /* 104 * EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying 105 * the file as an ELF object file 106 */ 107 #define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ 108 #define ELFMAG1 'E' /* e_ident[EI_MAG1] */ 109 #define ELFMAG2 'L' /* e_ident[EI_MAG2] */ 110 #define ELFMAG3 'F' /* e_ident[EI_MAG3] */ 111 #define ELFMAG "\177ELF" 112 #define SELFMAG 4 113 114 /* 115 * EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or 116 * capacity. 117 */ 118 #define ELFCLASSNONE 0 /* Invalid class */ 119 #define ELFCLASS32 1 /* 32-bit objects */ 120 #define ELFCLASS64 2 /* 64-bit objects */ 121 122 /* 123 * EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the 124 * remote_proc-specific data in the object file. The following encodings are 125 * currently defined. 126 */ 127 #define ELFDATANONE 0 /* Invalid data encoding */ 128 #define ELFDATA2LSB 1 /* See Data encodings, below */ 129 #define ELFDATA2MSB 2 /* See Data encodings, below */ 130 131 /* EI_OSABI - We do not define an OS specific ABI */ 132 #define ELFOSABI_NONE 0 133 134 /* ELF32 program header */ 135 typedef struct elf32_phdr { 136 Elf32_Word p_type; 137 Elf32_Off p_offset; 138 Elf32_Addr p_vaddr; 139 Elf32_Addr p_paddr; 140 Elf32_Word p_filesz; 141 Elf32_Word p_memsz; 142 Elf32_Word p_flags; 143 Elf32_Word p_align; 144 } Elf32_Phdr; 145 146 /* ELF64 program header */ 147 typedef struct elf64_phdr { 148 Elf64_Word p_type; 149 Elf64_Word p_flags; 150 Elf64_Off p_offset; 151 Elf64_Addr p_vaddr; 152 Elf64_Addr p_paddr; 153 Elf64_Xword p_filesz; 154 Elf64_Xword p_memsz; 155 Elf64_Xword p_align; 156 } Elf64_Phdr; 157 158 /* segment types */ 159 #define PT_NULL 0 160 #define PT_LOAD 1 161 #define PT_DYNAMIC 2 162 #define PT_INTERP 3 163 #define PT_NOTE 4 164 #define PT_SHLIB 5 165 #define PT_PHDR 6 166 #define PT_TLS 7 /* Thread local storage segment */ 167 #define PT_LOOS 0x60000000 /* OS-specific */ 168 #define PT_HIOS 0x6fffffff /* OS-specific */ 169 #define PT_LOPROC 0x70000000 170 #define PT_HIPROC 0x7fffffff 171 172 /* ELF32 section header. */ 173 typedef struct { 174 Elf32_Word sh_name; 175 Elf32_Word sh_type; 176 Elf32_Word sh_flags; 177 Elf32_Addr sh_addr; 178 Elf32_Off sh_offset; 179 Elf32_Word sh_size; 180 Elf32_Word sh_link; 181 Elf32_Word sh_info; 182 Elf32_Word sh_addralign; 183 Elf32_Word sh_entsize; 184 } Elf32_Shdr; 185 186 /* ELF64 section header. */ 187 typedef struct { 188 Elf64_Word sh_name; 189 Elf64_Word sh_type; 190 Elf64_Xword sh_flags; 191 Elf64_Addr sh_addr; 192 Elf64_Off sh_offset; 193 Elf64_Xword sh_size; 194 Elf64_Word sh_link; 195 Elf64_Word sh_info; 196 Elf64_Xword sh_addralign; 197 Elf64_Xword sh_entsize; 198 } Elf64_Shdr; 199 200 /* sh_type */ 201 #define SHT_NULL 0 202 #define SHT_PROGBITS 1 203 #define SHT_SYMTAB 2 204 #define SHT_STRTAB 3 205 #define SHT_RELA 4 206 #define SHT_HASH 5 207 #define SHT_DYNAMIC 6 208 #define SHT_NOTE 7 209 #define SHT_NOBITS 8 210 #define SHT_REL 9 211 #define SHT_SHLIB 10 212 #define SHT_DYNSYM 11 213 #define SHT_INIT_ARRAY 14 214 #define SHT_FINI_ARRAY 15 215 #define SHT_PREINIT_ARRAY 16 216 #define SHT_GROUP 17 217 #define SHT_SYMTAB_SHNDX 18 218 #define SHT_LOOS 0x60000000 219 #define SHT_HIOS 0x6fffffff 220 #define SHT_LOPROC 0x70000000 221 #define SHT_HIPROC 0x7fffffff 222 #define SHT_LOUSER 0x80000000 223 #define SHT_HIUSER 0xffffffff 224 225 /* sh_flags */ 226 #define SHF_WRITE 0x1 227 #define SHF_ALLOC 0x2 228 #define SHF_EXECINSTR 0x4 229 #define SHF_MASKPROC 0xf0000000 230 231 /* Relocation entry (without addend) */ 232 typedef struct { 233 Elf32_Addr r_offset; 234 Elf32_Word r_info; 235 } Elf32_Rel; 236 237 typedef struct { 238 Elf64_Addr r_offset; 239 Elf64_Xword r_info; 240 } Elf64_Rel; 241 242 /* Relocation entry with addend */ 243 typedef struct { 244 Elf32_Addr r_offset; 245 Elf32_Word r_info; 246 Elf32_Sword r_addend; 247 } Elf32_Rela; 248 249 typedef struct elf64_rela { 250 Elf64_Addr r_offset; 251 Elf64_Xword r_info; 252 Elf64_Sxword r_addend; 253 } Elf64_Rela; 254 255 /* Macros to extract information from 'r_info' field of relocation entries */ 256 #define ELF32_R_SYM(i) ((i) >> 8) 257 #define ELF32_R_TYPE(i) ((unsigned char)(i)) 258 #define ELF64_R_SYM(i) ((i) >> 32) 259 #define ELF64_R_TYPE(i) ((i) & 0xffffffff) 260 261 /* Symbol table entry */ 262 typedef struct { 263 Elf32_Word st_name; 264 Elf32_Addr st_value; 265 Elf32_Word st_size; 266 unsigned char st_info; 267 unsigned char st_other; 268 Elf32_Half st_shndx; 269 } Elf32_Sym; 270 271 typedef struct elf64_sym { 272 Elf64_Word st_name; 273 unsigned char st_info; 274 unsigned char st_other; 275 Elf64_Half st_shndx; 276 Elf64_Addr st_value; 277 Elf64_Xword st_size; 278 } Elf64_Sym; 279 280 /* ARM specific dynamic relocation codes */ 281 #define R_ARM_GLOB_DAT 21 /* 0x15 */ 282 #define R_ARM_JUMP_SLOT 22 /* 0x16 */ 283 #define R_ARM_RELATIVE 23 /* 0x17 */ 284 #define R_ARM_ABS32 2 /* 0x02 */ 285 286 /* ELF decoding information */ 287 struct elf32_info { 288 Elf32_Ehdr ehdr; 289 int load_state; 290 Elf32_Phdr *phdrs; 291 Elf32_Shdr *shdrs; 292 void *shstrtab; 293 }; 294 295 struct elf64_info { 296 Elf64_Ehdr ehdr; 297 int load_state; 298 Elf64_Phdr *phdrs; 299 Elf64_Shdr *shdrs; 300 void *shstrtab; 301 }; 302 303 #define ELF_STATE_INIT 0x0L 304 #define ELF_STATE_WAIT_FOR_PHDRS 0x100L 305 #define ELF_STATE_WAIT_FOR_SHDRS 0x200L 306 #define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400L 307 #define ELF_STATE_HDRS_COMPLETE 0x800L 308 #define ELF_STATE_MASK 0xFF00L 309 #define ELF_NEXT_SEGMENT_MASK 0x00FFL 310 311 extern const struct loader_ops elf_ops; 312 313 /** 314 * @internal 315 * 316 * @brief Check if it is an ELF file 317 * 318 * It will check if the input image header is an ELF header. 319 * 320 * @param img_data Firmware private data which will be passed to user 321 * defined loader operations 322 * @param len Firmware header length 323 * 324 * @return 0 for success or negative value for failure. 325 */ 326 int elf_identify(const void *img_data, size_t len); 327 328 /** 329 * @internal 330 * 331 * @brief Load ELF headers 332 * 333 * It will get the ELF header, the program header, and the section header. 334 * 335 * @param img_data Image data 336 * @param offset Input image data offset to the start of image 337 * file 338 * @param len Input image data length 339 * @param img_info Pointer to store image information data 340 * @param last_load_state Last state return by this function 341 * @param noffset Pointer to next offset required by loading ELF 342 * header 343 * @param nlen Pointer to next data length required by loading 344 * ELF header 345 * 346 * @return ELF loading header state, or negative value for failure 347 */ 348 int elf_load_header(const void *img_data, size_t offset, size_t len, 349 void **img_info, int last_load_state, 350 size_t *noffset, size_t *nlen); 351 352 /** 353 * @internal 354 * 355 * @brief Load ELF data 356 * 357 * It will parse the ELF image and return the target device address, 358 * offset to the start of the ELF image of the data to load and the 359 * length of the data to load. 360 * 361 * @param rproc Pointer to remoteproc instance 362 * @param img_data Image data which will passed to the function. 363 * it can be NULL, if image data doesn't need to 364 * be handled by the load function. E.g. binary 365 * data which was loaded to the target memory. 366 * @param offset Last loaded image data offset to the start of 367 * image file 368 * @param len Last loaded image data length 369 * @param img_info Pointer to store image information data 370 * @param last_load_state The returned state of the last function call. 371 * @param da Target device address, if the data to load is 372 * not for target memory the da will be set to 373 * ANY. 374 * @param noffset Pointer to next offset required by loading ELF 375 * header 376 * @param nlen Pointer to next data length required by loading 377 * ELF header 378 * @param padding Value to pad it is possible that a size of a 379 * segment in memory is larger than what it is in 380 * the ELF image. e.g. a segment can have stack 381 * section .bss. It doesn't need to copy image 382 * file space, in this case, it will be packed 383 * with 0. 384 * @param nmemsize Pointer to next data target memory size. The 385 * size of a segment in the target memory can be 386 * larger than the its size in the image file. 387 * 388 * @return 0 for success, otherwise negative value for failure 389 */ 390 int elf_load(struct remoteproc *rproc, const void *img_data, 391 size_t offset, size_t len, 392 void **img_info, int last_load_state, 393 metal_phys_addr_t *da, 394 size_t *noffset, size_t *nlen, 395 unsigned char *padding, size_t *nmemsize); 396 397 /** 398 * @internal 399 * 400 * @brief Release ELF image information 401 * 402 * It will release ELF image information data. 403 * 404 * @param img_info Pointer to ELF image information 405 */ 406 void elf_release(void *img_info); 407 408 /** 409 * @internal 410 * 411 * @brief Get entry point 412 * 413 * It will return entry point specified in the ELF file. 414 * 415 * @param img_info Pointer to ELF image information 416 * 417 * @return Entry address 418 */ 419 metal_phys_addr_t elf_get_entry(void *img_info); 420 421 /** 422 * @internal 423 * 424 * @brief Locate the resource table information 425 * 426 * It will return the length of the resource table, and the device address of 427 * the resource table. 428 * 429 * @param img_info Pointer to ELF image information 430 * @param da Pointer to the device address 431 * @param offset Pointer to the offset to in the ELF image of the 432 * resource table section. 433 * @param size Pointer to the size of the resource table section. 434 * 435 * @return 0 if successfully locate the resource table, negative value for 436 * failure. 437 */ 438 int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da, 439 size_t *offset, size_t *size); 440 441 #if defined __cplusplus 442 } 443 #endif 444 445 #endif /* ELF_LOADER_H_ */ 446