1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2023 Corigine, Inc. 3 * All rights reserved. 4 */ 5 6 #include "nfp_elf.h" 7 8 #include <malloc.h> 9 #include <stdbool.h> 10 #include <ethdev_pci.h> 11 12 #include <nfp_platform.h> 13 #include <rte_common.h> 14 #include <eal_firmware.h> 15 16 #include "nfp_logs.h" 17 #include "nfp_mip.h" 18 19 /* 20 * NFP Chip Families. 21 * 22 * These are not enums, because they need to be microcode compatible. 23 * They are also not maskable. 24 * 25 * Note: The NFP-4xxx family is handled as NFP-6xxx in most software 26 * components. 27 */ 28 #define NFP_CHIP_FAMILY_NFP3800 0x3800 29 #define NFP_CHIP_FAMILY_NFP6000 0x6000 30 31 /* Standard ELF */ 32 #define NFP_ELF_EI_NIDENT 16 33 #define NFP_ELF_EI_MAG0 0 34 #define NFP_ELF_EI_MAG1 1 35 #define NFP_ELF_EI_MAG2 2 36 #define NFP_ELF_EI_MAG3 3 37 #define NFP_ELF_EI_CLASS 4 38 #define NFP_ELF_EI_DATA 5 39 #define NFP_ELF_EI_VERSION 6 40 #define NFP_ELF_EI_PAD 7 41 #define NFP_ELF_ELFMAG0 0x7f 42 #define NFP_ELF_ELFMAG1 'E' 43 #define NFP_ELF_ELFMAG2 'L' 44 #define NFP_ELF_ELFMAG3 'F' 45 #define NFP_ELF_ELFCLASSNONE 0 46 #define NFP_ELF_ELFCLASS32 1 47 #define NFP_ELF_ELFCLASS64 2 48 #define NFP_ELF_ELFDATANONE 0 49 #define NFP_ELF_ELFDATA2LSB 1 50 #define NFP_ELF_ELFDATA2MSB 2 51 52 #define NFP_ELF_ET_NONE 0 53 #define NFP_ELF_ET_REL 1 54 #define NFP_ELF_ET_EXEC 2 55 #define NFP_ELF_ET_DYN 3 56 #define NFP_ELF_ET_CORE 4 57 #define NFP_ELF_ET_LOPROC 0xFF00 58 #define NFP_ELF_ET_HIPROC 0xFFFF 59 #define NFP_ELF_ET_NFP_PARTIAL_REL (NFP_ELF_ET_LOPROC + NFP_ELF_ET_REL) 60 #define NFP_ELF_ET_NFP_PARTIAL_EXEC (NFP_ELF_ET_LOPROC + NFP_ELF_ET_EXEC) 61 62 #define NFP_ELF_EM_NFP 250 63 #define NFP_ELF_EM_NFP6000 0x6000 64 65 #define NFP_ELF_SHT_NULL 0 66 #define NFP_ELF_SHT_PROGBITS 1 67 #define NFP_ELF_SHT_SYMTAB 2 68 #define NFP_ELF_SHT_STRTAB 3 69 #define NFP_ELF_SHT_RELA 4 70 #define NFP_ELF_SHT_HASH 5 71 #define NFP_ELF_SHT_DYNAMIC 6 72 #define NFP_ELF_SHT_NOTE 7 73 #define NFP_ELF_SHT_NOBITS 8 74 #define NFP_ELF_SHT_REL 9 75 #define NFP_ELF_SHT_SHLIB 10 76 #define NFP_ELF_SHT_DYNSYM 11 77 #define NFP_ELF_SHT_LOPROC 0x70000000 78 #define NFP_ELF_SHT_HIPROC 0x7fffffff 79 #define NFP_ELF_SHT_LOUSER 0x80000000 80 #define NFP_ELF_SHT_HIUSER 0x8fffffff 81 82 #define NFP_ELF_EV_NONE 0 83 #define NFP_ELF_EV_CURRENT 1 84 85 #define NFP_ELF_SHN_UNDEF 0 86 87 /* EM_NFP ELF flags */ 88 89 /* 90 * Valid values for FAMILY are: 91 * 0x6000 - NFP-6xxx/NFP-4xxx 92 * 0x3800 - NFP-38xx 93 */ 94 #define NFP_ELF_EF_NFP_FAMILY_MASK 0xFFFF 95 #define NFP_ELF_EF_NFP_FAMILY_LSB 8 96 97 #define NFP_ELF_SHT_NFP_MECONFIG (NFP_ELF_SHT_LOPROC + 1) 98 #define NFP_ELF_SHT_NFP_INITREG (NFP_ELF_SHT_LOPROC + 2) 99 #define NFP_ELF_SHT_UOF_DEBUG (NFP_ELF_SHT_LOUSER) 100 101 /* NFP target revision note type */ 102 #define NFP_ELT_NOTE_NAME_NFP "NFP\0" 103 #define NFP_ELT_NOTE_NAME_NFP_SZ 4 104 #define NFP_ELT_NOTE_NAME_NFP_USER "NFP_USR\0" 105 #define NFP_ELT_NOTE_NAME_NFP_USER_SZ 8 106 #define NFP_ELF_NT_NFP_BUILD_INFO 0x100 107 #define NFP_ELF_NT_NFP_REVS 0x101 108 #define NFP_ELF_NT_NFP_MIP_LOCATION 0x102 109 #define NFP_ELF_NT_NFP_USER 0xf0000000 110 111 112 /* Standard ELF structures */ 113 struct nfp_elf_elf64_ehdr { 114 uint8_t e_ident[NFP_ELF_EI_NIDENT]; 115 rte_le16_t e_type; 116 rte_le16_t e_machine; 117 rte_le32_t e_version; 118 rte_le64_t e_entry; 119 rte_le64_t e_phoff; 120 rte_le64_t e_shoff; 121 rte_le32_t e_flags; 122 rte_le16_t e_ehsize; 123 rte_le16_t e_phentsize; 124 rte_le16_t e_phnum; 125 rte_le16_t e_shentsize; 126 rte_le16_t e_shnum; 127 rte_le16_t e_shstrndx; 128 }; 129 130 struct nfp_elf_elf64_shdr { 131 rte_le32_t sh_name; 132 rte_le32_t sh_type; 133 rte_le64_t sh_flags; 134 rte_le64_t sh_addr; 135 rte_le64_t sh_offset; 136 rte_le64_t sh_size; 137 rte_le32_t sh_link; 138 rte_le32_t sh_info; 139 rte_le64_t sh_addralign; 140 rte_le64_t sh_entsize; 141 }; 142 143 struct nfp_elf_elf64_sym { 144 rte_le32_t st_name; 145 uint8_t st_info; 146 uint8_t st_other; 147 rte_le16_t st_shndx; 148 rte_le64_t st_value; 149 rte_le64_t st_size; 150 }; 151 152 struct nfp_elf_elf64_rel { 153 rte_le64_t r_offset; 154 rte_le64_t r_info; 155 }; 156 157 struct nfp_elf_elf64_nhdr { 158 rte_le32_t n_namesz; 159 rte_le32_t n_descsz; 160 rte_le32_t n_type; 161 }; 162 163 /* NFP specific structures */ 164 struct nfp_elf_elf_meconfig { 165 rte_le32_t ctx_enables; 166 rte_le32_t entry; 167 rte_le32_t misc_control; 168 rte_le32_t reserved; 169 }; 170 171 struct nfp_elf_elf_initregentry { 172 rte_le32_t w0; 173 rte_le32_t cpp_offset_lo; 174 rte_le32_t val; 175 rte_le32_t mask; 176 }; 177 178 /* NFP NFFW ELF struct and API */ 179 struct nfp_elf_user_note { 180 const char *name; 181 uint32_t data_sz; 182 void *data; 183 }; 184 185 /* 186 * nfp_elf_fw_mip contains firmware related fields from the MIP as well as the 187 * MIP location in the NFFW file. All fields are only valid if shndx > 0. 188 * 189 * This struct will only be available if the firmware contains a .note section 190 * with a note of type NFP_ELF_NT_NFP_MIP_LOCATION. 191 */ 192 struct nfp_elf_fw_mip { 193 size_t shndx; 194 uint64_t sh_offset; 195 rte_le32_t mip_ver; /**< Version of the format of the MIP itself */ 196 197 rte_le32_t fw_version; 198 rte_le32_t fw_buildnum; 199 rte_le32_t fw_buildtime; 200 char fw_name[20]; /**< At most 16 chars, 17 ensures '\0', round up */ 201 const char *fw_typeid; /**< NULL if none set */ 202 }; 203 204 /* 205 * It is preferred to access this struct via the nfp_elf functions 206 * rather than directly. 207 */ 208 struct nfp_elf { 209 struct nfp_elf_elf64_ehdr *ehdr; 210 struct nfp_elf_elf64_shdr *shdrs; 211 size_t shdrs_cnt; 212 void **shdrs_data; 213 214 /** True if section data has been endian swapped */ 215 uint8_t *shdrs_host_endian; 216 217 size_t shdr_idx_symtab; 218 219 struct nfp_elf_elf64_sym *syms; 220 size_t syms_cnt; 221 222 char *shstrtab; 223 size_t shstrtab_sz; 224 225 char *symstrtab; 226 size_t symstrtab_sz; 227 228 struct nfp_elf_elf_meconfig *meconfs; 229 size_t meconfs_cnt; 230 231 /* ==== .note data start ==== */ 232 233 /** 234 * Following data derived from SHT_NOTE sections for read-only usage. 235 * These fields are not used in nfp_elf_to_buf() 236 */ 237 int rev_min; /**< -1 if file did not specify */ 238 int rev_max; /**< -1 if file did not specify */ 239 240 /** 241 * If mip_shndx == 0 and mip_sh_off == 0, the .note stated there is no MIP. 242 * If mip_shndx == 0 and mip_sh_off == UINT64_MAX, there was no .note and 243 * a MIP _may_ still be found in the first 256KiB of DRAM/EMEM data. 244 */ 245 size_t mip_shndx; /**< Section in which MIP resides, 0 if no MIP */ 246 uint64_t mip_sh_off; /**< Offset within section (not address) */ 247 248 struct nfp_elf_fw_mip fw_mip; 249 const char *fw_info_strtab; 250 size_t fw_info_strtab_sz; 251 252 /* ==== .note.user data start ==== */ 253 size_t user_note_cnt; 254 struct nfp_elf_user_note *user_notes; 255 256 void *dbgdata; 257 258 int family; 259 260 /** 261 * For const entry points in the API, we allocate and keep a buffer 262 * and for mutable entry points we assume the buffer remains valid 263 * and we just set pointers to it. 264 */ 265 void *_buf; 266 size_t _bufsz; 267 }; 268 269 static void 270 nfp_elf_free(struct nfp_elf *ectx) 271 { 272 if (ectx == NULL) 273 return; 274 275 free(ectx->shdrs); 276 free(ectx->shdrs_data); 277 free(ectx->shdrs_host_endian); 278 if (ectx->_bufsz != 0) 279 free(ectx->_buf); 280 281 free(ectx); 282 } 283 284 static size_t 285 nfp_elf_get_sec_ent_cnt(struct nfp_elf *ectx, 286 size_t idx) 287 { 288 uint64_t sh_size = rte_le_to_cpu_64(ectx->shdrs[idx].sh_size); 289 uint64_t sh_entsize = rte_le_to_cpu_64(ectx->shdrs[idx].sh_entsize); 290 291 if (sh_entsize != 0) 292 return sh_size / sh_entsize; 293 294 return 0; 295 } 296 297 static bool 298 nfp_elf_check_sh_size(uint64_t sh_size) 299 { 300 if (sh_size == 0 || sh_size > UINT32_MAX) 301 return false; 302 303 return true; 304 } 305 306 static const char * 307 nfp_elf_fwinfo_next(struct nfp_elf *ectx, 308 const char *key_val) 309 { 310 size_t s_len; 311 const char *strtab = ectx->fw_info_strtab; 312 ssize_t tab_sz = (ssize_t)ectx->fw_info_strtab_sz; 313 314 if (key_val == NULL) 315 return strtab; 316 317 s_len = strlen(key_val); 318 if (key_val < strtab || ((key_val + s_len + 1) >= (strtab + tab_sz - 1))) 319 return NULL; 320 321 key_val += s_len + 1; 322 323 return key_val; 324 } 325 326 static const char * 327 nfp_elf_fwinfo_lookup(struct nfp_elf *ectx, 328 const char *key) 329 { 330 size_t s_len; 331 const char *s; 332 size_t key_len = strlen(key); 333 const char *strtab = ectx->fw_info_strtab; 334 ssize_t tab_sz = (ssize_t)ectx->fw_info_strtab_sz; 335 336 if (strtab == NULL) 337 return NULL; 338 339 for (s = strtab, s_len = strlen(s) + 1; 340 (s[0] != '\0') && (tab_sz > 0); 341 s_len = strlen(s) + 1, tab_sz -= s_len, s += s_len) { 342 if ((strncmp(s, key, key_len) == 0) && (s[key_len] == '=')) 343 return &s[key_len + 1]; 344 } 345 346 return NULL; 347 } 348 349 static bool 350 nfp_elf_arch_is_thornham(struct nfp_elf *ectx) 351 { 352 if (ectx == NULL) 353 return false; 354 355 if (ectx->family == NFP_CHIP_FAMILY_NFP6000 || ectx->family == NFP_CHIP_FAMILY_NFP3800) 356 return true; 357 358 return false; 359 } 360 361 static int 362 nfp_elf_parse_sht_rel(struct nfp_elf_elf64_shdr *sec, 363 struct nfp_elf *ectx, 364 size_t idx, 365 uint8_t *buf8) 366 { 367 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 368 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 369 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 370 371 if (sh_entsize != sizeof(struct nfp_elf_elf64_rel)) { 372 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 373 return -EINVAL; 374 } 375 376 if (!nfp_elf_check_sh_size(sh_size)) { 377 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 378 return -EINVAL; 379 } 380 381 ectx->shdrs_data[idx] = buf8 + sh_offset; 382 ectx->shdrs_host_endian[idx] = 1; 383 384 return 0; 385 } 386 387 static int 388 nfp_elf_parse_note_name_nfp(struct nfp_elf *ectx, 389 size_t idx, 390 uint32_t ndescsz, 391 uint32_t ntype, 392 const char *nname, 393 rte_le32_t *descword) 394 { 395 if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP, NFP_ELT_NOTE_NAME_NFP_SZ) == 0) { 396 switch (ntype) { 397 case NFP_ELF_NT_NFP_REVS: 398 if (ndescsz != 8) { 399 PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); 400 return -EINVAL; 401 } 402 403 ectx->rev_min = (int)rte_le_to_cpu_32(descword[0]); 404 ectx->rev_max = (int)rte_le_to_cpu_32(descword[1]); 405 break; 406 case NFP_ELF_NT_NFP_MIP_LOCATION: 407 if (ndescsz != 12) { 408 PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); 409 return -EINVAL; 410 } 411 412 ectx->mip_shndx = rte_le_to_cpu_32(descword[0]); 413 if (ectx->mip_shndx == 0) { 414 ectx->mip_sh_off = 0; 415 break; 416 } 417 418 if (ectx->mip_shndx >= ectx->shdrs_cnt) { 419 PMD_DRV_LOG(ERR, "Invalid ELF NOTE shndx in section %zu.", idx); 420 return -EINVAL; 421 } 422 423 ectx->mip_sh_off = rte_le_to_cpu_32(descword[1]) | 424 (uint64_t)rte_le_to_cpu_32(descword[2]) << 32; 425 break; 426 default: 427 break; 428 } 429 } else if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, 430 NFP_ELT_NOTE_NAME_NFP_USER_SZ) == 0 && ntype == NFP_ELF_NT_NFP_USER) { 431 ectx->user_note_cnt++; 432 } 433 434 return 0; 435 } 436 437 static int 438 nfp_elf_parse_sht_note(struct nfp_elf_elf64_shdr *sec, 439 struct nfp_elf *ectx, 440 size_t idx, 441 uint8_t *buf8) 442 { 443 int err; 444 size_t nsz; 445 uint8_t *desc; 446 uint32_t ntype; 447 uint32_t nnamesz; 448 uint32_t ndescsz; 449 const char *nname; 450 uint8_t *shdrs_data; 451 rte_le32_t *descword; 452 struct nfp_elf_elf64_nhdr *nhdr; 453 struct nfp_elf_user_note *unote; 454 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 455 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 456 457 if (!nfp_elf_check_sh_size(sh_size)) { 458 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 459 return -EINVAL; 460 } 461 462 shdrs_data = buf8 + sh_offset; 463 ectx->shdrs_data[idx] = shdrs_data; 464 ectx->shdrs_host_endian[idx] = 0; 465 466 /* Extract notes that we recognise */ 467 nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; 468 469 while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { 470 nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); 471 ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); 472 ntype = rte_le_to_cpu_32(nhdr->n_type); 473 nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); 474 descword = (rte_le32_t *)((uint8_t *)nhdr + sizeof(*nhdr) + 475 ((nnamesz + UINT32_C(3)) & ~UINT32_C(3))); 476 477 err = nfp_elf_parse_note_name_nfp(ectx, idx, ndescsz, ntype, nname, descword); 478 if (err != 0) 479 return err; 480 481 nhdr = (struct nfp_elf_elf64_nhdr *)((uint8_t *)descword + 482 ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); 483 } 484 485 if (ectx->user_note_cnt == 0) 486 return 0; 487 488 ectx->user_notes = calloc(ectx->user_note_cnt, sizeof(*ectx->user_notes)); 489 if (ectx->user_notes == NULL) { 490 PMD_DRV_LOG(ERR, "Out of memory."); 491 return -ENOMEM; 492 } 493 494 nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; 495 unote = ectx->user_notes; 496 while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { 497 nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); 498 ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); 499 ntype = rte_le_to_cpu_32(nhdr->n_type); 500 nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); 501 desc = (uint8_t *)nhdr + sizeof(*nhdr) + 502 ((nnamesz + UINT32_C(3)) & ~UINT32_C(3)); 503 504 if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, 505 NFP_ELT_NOTE_NAME_NFP_USER_SZ) != 0) 506 continue; 507 508 if (ntype != NFP_ELF_NT_NFP_USER) 509 continue; 510 511 unote->name = (const char *)desc; 512 nsz = strlen(unote->name) + 1; 513 if (nsz % 4 != 0) 514 nsz = ((nsz / 4) + 1) * 4; 515 if (nsz > ndescsz) { 516 PMD_DRV_LOG(ERR, "Invalid ELF USER NOTE descsz in section %zu.", idx); 517 return -EINVAL; 518 } 519 520 unote->data_sz = ndescsz - (uint32_t)nsz; 521 if (unote->data_sz != 0) 522 unote->data = desc + nsz; 523 unote++; 524 525 nhdr = (struct nfp_elf_elf64_nhdr *) 526 (desc + ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); 527 } 528 529 return 0; 530 } 531 532 static int 533 nfp_elf_parse_sht_meconfig(struct nfp_elf_elf64_shdr *sec, 534 struct nfp_elf *ectx, 535 size_t idx, 536 uint8_t *buf8) 537 { 538 size_t ent_cnt; 539 uint8_t *shdrs_data; 540 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 541 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 542 543 if (!nfp_elf_check_sh_size(sh_size)) { 544 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 545 return -EINVAL; 546 } 547 548 shdrs_data = buf8 + sh_offset; 549 ent_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); 550 ectx->shdrs_data[idx] = shdrs_data; 551 ectx->meconfs = (struct nfp_elf_elf_meconfig *)shdrs_data; 552 ectx->meconfs_cnt = ent_cnt; 553 ectx->shdrs_host_endian[idx] = 1; 554 555 return 0; 556 } 557 558 static int 559 nfp_elf_parse_sht_initreg(struct nfp_elf_elf64_shdr *sec, 560 struct nfp_elf *ectx, 561 size_t idx, 562 uint8_t *buf8) 563 { 564 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 565 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 566 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 567 568 if (!nfp_elf_arch_is_thornham(ectx)) { 569 PMD_DRV_LOG(ERR, "Section not supported for target arch."); 570 return -ENOTSUP; 571 } 572 573 if (sh_entsize != sizeof(struct nfp_elf_elf_initregentry) || 574 !nfp_elf_check_sh_size(sh_size)) { 575 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 576 return -EINVAL; 577 } 578 579 ectx->shdrs_data[idx] = buf8 + sh_offset; 580 ectx->shdrs_host_endian[idx] = 1; 581 582 return 0; 583 } 584 585 static int 586 nfp_elf_parse_sht_symtab(struct nfp_elf_elf64_shdr *sec, 587 struct nfp_elf *ectx, 588 size_t idx, 589 uint8_t *buf8) 590 { 591 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 592 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 593 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 594 595 if (sh_entsize != sizeof(struct nfp_elf_elf64_sym) || 596 !nfp_elf_check_sh_size(sh_size)) { 597 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 598 return -EINVAL; 599 } 600 601 ectx->shdrs_data[idx] = buf8 + sh_offset; 602 ectx->shdrs_host_endian[ectx->shdr_idx_symtab] = 1; 603 604 return 0; 605 } 606 607 static int 608 nfp_elf_populate_fw_mip(struct nfp_elf *ectx, 609 uint8_t *buf8) 610 { 611 uint8_t *pu8; 612 const char *nx; 613 uint64_t sh_size; 614 uint64_t sh_offset; 615 uint32_t first_entry; 616 const struct nfp_mip *mip; 617 struct nfp_elf_elf64_shdr *sec; 618 const struct nfp_mip_entry *ent; 619 const struct nfp_mip_fwinfo_entry *fwinfo; 620 621 sec = &ectx->shdrs[ectx->mip_shndx]; 622 sh_size = rte_le_to_cpu_64(sec->sh_size); 623 sh_offset = rte_le_to_cpu_64(sec->sh_offset); 624 pu8 = buf8 + sh_offset + ectx->mip_sh_off; 625 mip = (const struct nfp_mip *)pu8; 626 first_entry = rte_le_to_cpu_32(mip->first_entry); 627 628 if (mip->signature != NFP_MIP_SIGNATURE) { 629 PMD_DRV_LOG(ERR, "Incorrect MIP signature %#08x", 630 rte_le_to_cpu_32(mip->signature)); 631 return -EINVAL; 632 } 633 634 ectx->fw_mip.shndx = ectx->mip_shndx; 635 ectx->fw_mip.sh_offset = ectx->mip_sh_off; 636 ectx->fw_mip.mip_ver = mip->mip_version; 637 638 if (ectx->fw_mip.mip_ver != NFP_MIP_VERSION) { 639 PMD_DRV_LOG(ERR, "MIP note pointer does not point to recognised version."); 640 return -EINVAL; 641 } 642 643 ectx->fw_mip.fw_version = mip->version; 644 ectx->fw_mip.fw_buildnum = mip->buildnum; 645 ectx->fw_mip.fw_buildtime = mip->buildtime; 646 strncpy(ectx->fw_mip.fw_name, mip->name, 16); 647 648 /* 649 * If there is a FWINFO v1 entry, it will be first and 650 * right after the MIP itself, so in the same section. 651 */ 652 if (ectx->mip_sh_off + first_entry + sizeof(*ent) < sh_size) { 653 pu8 += first_entry; 654 ent = (const struct nfp_mip_entry *)pu8; 655 if (ent->type == NFP_MIP_TYPE_FWINFO && ent->version == 1) { 656 pu8 += sizeof(*ent); 657 fwinfo = (const struct nfp_mip_fwinfo_entry *)pu8; 658 if (fwinfo->kv_len != 0) { 659 ectx->fw_info_strtab_sz = fwinfo->kv_len; 660 ectx->fw_info_strtab = fwinfo->key_value_strs; 661 } 662 } 663 } 664 665 ectx->fw_mip.fw_typeid = nfp_elf_fwinfo_lookup(ectx, "TypeId"); 666 667 /* 668 * TypeId will be the last reserved key-value pair, so skip 669 * to the first entry after it for the user values. 670 */ 671 if (ectx->fw_mip.fw_typeid == NULL) 672 return 0; 673 674 nx = nfp_elf_fwinfo_next(ectx, ectx->fw_mip.fw_typeid); 675 if (nx == NULL) 676 ectx->fw_info_strtab_sz = 0; 677 else 678 ectx->fw_info_strtab_sz -= (nx - ectx->fw_info_strtab); 679 ectx->fw_info_strtab = nx; 680 681 return 0; 682 } 683 684 static int 685 nfp_elf_read_file_headers(struct nfp_elf *ectx, 686 void *buf) 687 { 688 uint16_t e_type; 689 uint32_t e_flags; 690 uint32_t e_version; 691 uint16_t e_machine; 692 693 ectx->ehdr = buf; 694 e_type = rte_le_to_cpu_16(ectx->ehdr->e_type); 695 e_flags = rte_le_to_cpu_32(ectx->ehdr->e_flags); 696 e_version = rte_le_to_cpu_32(ectx->ehdr->e_version); 697 e_machine = rte_le_to_cpu_16(ectx->ehdr->e_machine); 698 699 switch (e_machine) { 700 case NFP_ELF_EM_NFP: 701 ectx->family = (e_flags >> NFP_ELF_EF_NFP_FAMILY_LSB) 702 & NFP_ELF_EF_NFP_FAMILY_MASK; 703 break; 704 case NFP_ELF_EM_NFP6000: 705 ectx->family = NFP_CHIP_FAMILY_NFP6000; 706 break; 707 default: 708 PMD_DRV_LOG(ERR, "Invalid ELF machine type."); 709 return -EINVAL; 710 } 711 712 if ((e_type != NFP_ELF_ET_EXEC && e_type != NFP_ELF_ET_REL && 713 e_type != NFP_ELF_ET_NFP_PARTIAL_EXEC && 714 e_type != NFP_ELF_ET_NFP_PARTIAL_REL) || 715 e_version != NFP_ELF_EV_CURRENT || 716 ectx->ehdr->e_ehsize != sizeof(struct nfp_elf_elf64_ehdr) || 717 ectx->ehdr->e_shentsize != sizeof(struct nfp_elf_elf64_shdr)) { 718 PMD_DRV_LOG(ERR, "Invalid ELF file header."); 719 return -EINVAL; 720 } 721 722 if (ectx->ehdr->e_shoff < ectx->ehdr->e_ehsize) { 723 PMD_DRV_LOG(ERR, "Invalid ELF header content."); 724 return -EINVAL; 725 } 726 727 if (ectx->ehdr->e_shstrndx >= ectx->ehdr->e_shnum) { 728 PMD_DRV_LOG(ERR, "Invalid ELF header content."); 729 return -EINVAL; 730 } 731 732 return 0; 733 } 734 735 static int 736 nfp_elf_read_section_headers(struct nfp_elf *ectx, 737 uint8_t *buf8, 738 size_t buf_len) 739 { 740 size_t idx; 741 int err = 0; 742 uint8_t *pu8; 743 uint64_t sh_size; 744 uint64_t sh_offset; 745 uint64_t sh_entsize; 746 struct nfp_elf_elf64_shdr *sec; 747 uint64_t e_shoff = rte_le_to_cpu_16(ectx->ehdr->e_shoff); 748 uint16_t e_shnum = rte_le_to_cpu_16(ectx->ehdr->e_shnum); 749 750 if (buf_len < e_shoff + ((size_t)e_shnum * sizeof(*sec))) { 751 PMD_DRV_LOG(ERR, "ELF data too short."); 752 return -EINVAL; 753 } 754 755 pu8 = buf8 + e_shoff; 756 757 if (e_shnum == 0) { 758 ectx->shdrs = NULL; 759 ectx->shdrs_data = NULL; 760 ectx->shdrs_host_endian = NULL; 761 ectx->shdrs_cnt = 0; 762 return 0; 763 } 764 765 ectx->shdrs = calloc(e_shnum, sizeof(*ectx->shdrs)); 766 if (ectx->shdrs == NULL) { 767 PMD_DRV_LOG(ERR, "Out of memory."); 768 return -ENOMEM; 769 } 770 771 ectx->shdrs_data = calloc(e_shnum, sizeof(void *)); 772 if (ectx->shdrs_data == NULL) { 773 PMD_DRV_LOG(ERR, "Out of memory."); 774 err = -ENOMEM; 775 goto free_shdrs; 776 } 777 778 ectx->shdrs_host_endian = calloc(e_shnum, sizeof(ectx->shdrs_host_endian[0])); 779 if (ectx->shdrs_host_endian == NULL) { 780 PMD_DRV_LOG(ERR, "Out of memory."); 781 err = -ENOMEM; 782 goto free_shdrs_data; 783 } 784 785 memcpy(ectx->shdrs, pu8, e_shnum * sizeof(*ectx->shdrs)); 786 ectx->shdrs_cnt = e_shnum; 787 788 for (idx = 0, sec = ectx->shdrs; idx < ectx->shdrs_cnt; idx++, sec++) { 789 sh_size = rte_le_to_cpu_64(sec->sh_size); 790 sh_offset = rte_le_to_cpu_64(sec->sh_offset); 791 sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 792 793 if (sh_entsize != 0 && (sh_size % sh_entsize != 0)) { 794 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 795 err = -EINVAL; 796 goto free_shdrs_host_endian; 797 } 798 799 switch (rte_le_to_cpu_32(sec->sh_type)) { 800 case NFP_ELF_SHT_REL: 801 err = nfp_elf_parse_sht_rel(sec, ectx, idx, buf8); 802 if (err != 0) { 803 PMD_DRV_LOG(ERR, "Failed to parse sht rel."); 804 goto free_shdrs_host_endian; 805 } 806 break; 807 case NFP_ELF_SHT_NOTE: 808 err = nfp_elf_parse_sht_note(sec, ectx, idx, buf8); 809 if (err != 0) { 810 PMD_DRV_LOG(ERR, "Failed to parse sht note."); 811 goto free_shdrs_host_endian; 812 } 813 break; 814 case NFP_ELF_SHT_NFP_MECONFIG: 815 err = nfp_elf_parse_sht_meconfig(sec, ectx, idx, buf8); 816 if (err != 0) { 817 PMD_DRV_LOG(ERR, "Failed to parse sht meconfig."); 818 goto free_shdrs_host_endian; 819 } 820 break; 821 case NFP_ELF_SHT_NFP_INITREG: 822 err = nfp_elf_parse_sht_initreg(sec, ectx, idx, buf8); 823 if (err != 0) { 824 PMD_DRV_LOG(ERR, "Failed to parse sht initregp."); 825 goto free_shdrs_host_endian; 826 } 827 break; 828 case NFP_ELF_SHT_SYMTAB: 829 err = nfp_elf_parse_sht_symtab(sec, ectx, idx, buf8); 830 if (err != 0) { 831 PMD_DRV_LOG(ERR, "Failed to parse sht symtab."); 832 goto free_shdrs_host_endian; 833 } 834 break; 835 case NFP_ELF_SHT_NOBITS: 836 case NFP_ELF_SHT_NULL: 837 break; 838 default: 839 if (sh_offset > 0 && sh_size <= 0) 840 break; 841 842 /* 843 * Limit sections to 4GiB, because they won't need to be this large 844 * and this ensures we can handle the file on 32-bit hosts without 845 * unexpected problems. 846 */ 847 if (sh_size > UINT32_MAX) { 848 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 849 err = -EINVAL; 850 goto free_shdrs_host_endian; 851 } 852 853 pu8 = buf8 + sh_offset; 854 ectx->shdrs_data[idx] = pu8; 855 ectx->shdrs_host_endian[idx] = 0; 856 break; 857 } 858 } 859 860 return 0; 861 862 free_shdrs_host_endian: 863 free(ectx->shdrs_host_endian); 864 free_shdrs_data: 865 free(ectx->shdrs_data); 866 free_shdrs: 867 free(ectx->shdrs); 868 869 return err; 870 } 871 872 static int 873 nfp_elf_read_shstrtab(struct nfp_elf *ectx) 874 { 875 struct nfp_elf_elf64_shdr *sec; 876 uint16_t e_shstrndx = rte_le_to_cpu_16(ectx->ehdr->e_shstrndx); 877 878 if (ectx->ehdr->e_shnum <= ectx->ehdr->e_shstrndx) { 879 PMD_DRV_LOG(ERR, "Invalid Index."); 880 return -EINVAL; 881 } 882 883 sec = &ectx->shdrs[e_shstrndx]; 884 if (sec == NULL || rte_le_to_cpu_32(sec->sh_type) != NFP_ELF_SHT_STRTAB) { 885 PMD_DRV_LOG(ERR, "Invalid ELF shstrtab."); 886 return -EINVAL; 887 } 888 889 ectx->shstrtab = ectx->shdrs_data[e_shstrndx]; 890 ectx->shstrtab_sz = rte_le_to_cpu_64(sec->sh_size); 891 892 return 0; 893 } 894 895 static int 896 nfp_elf_read_first_symtab(struct nfp_elf *ectx) 897 { 898 size_t idx; 899 uint32_t sh_type; 900 uint64_t sh_size; 901 struct nfp_elf_elf64_shdr *sec; 902 903 for (idx = 0, sec = ectx->shdrs; idx < ectx->shdrs_cnt; idx++, sec++) { 904 if (sec != NULL) { 905 sh_type = rte_le_to_cpu_32(sec->sh_type); 906 if (sh_type == NFP_ELF_SHT_SYMTAB) 907 break; 908 } 909 } 910 911 sh_size = rte_le_to_cpu_64(sec->sh_size); 912 913 if (idx < ectx->shdrs_cnt && sh_type == NFP_ELF_SHT_SYMTAB) { 914 ectx->shdr_idx_symtab = idx; 915 ectx->syms = ectx->shdrs_data[idx]; 916 ectx->syms_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); 917 918 /* Load symtab's strtab */ 919 idx = rte_le_to_cpu_32(sec->sh_link); 920 921 if (idx == NFP_ELF_SHN_UNDEF || idx >= ectx->shdrs_cnt) { 922 PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); 923 return -EINVAL; 924 } 925 926 sec = &ectx->shdrs[idx]; 927 sh_type = rte_le_to_cpu_32(sec->sh_type); 928 if (sh_type != NFP_ELF_SHT_STRTAB) { 929 PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); 930 return -EINVAL; 931 } 932 933 if (!nfp_elf_check_sh_size(sh_size)) { 934 PMD_DRV_LOG(ERR, "ELF symtab has invalid strtab."); 935 return -EINVAL; 936 } 937 938 ectx->symstrtab = ectx->shdrs_data[idx]; 939 ectx->symstrtab_sz = sh_size; 940 } 941 942 return 0; 943 } 944 945 static int 946 nfp_elf_is_valid_file(uint8_t *buf8) 947 { 948 if (buf8[NFP_ELF_EI_MAG0] != NFP_ELF_ELFMAG0 || 949 buf8[NFP_ELF_EI_MAG1] != NFP_ELF_ELFMAG1 || 950 buf8[NFP_ELF_EI_MAG2] != NFP_ELF_ELFMAG2 || 951 buf8[NFP_ELF_EI_MAG3] != NFP_ELF_ELFMAG3 || 952 buf8[NFP_ELF_EI_VERSION] != NFP_ELF_EV_CURRENT || 953 buf8[NFP_ELF_EI_DATA] != NFP_ELF_ELFDATA2LSB) 954 return -EINVAL; 955 956 return 0; 957 } 958 959 static int 960 nfp_elf_is_valid_class(uint8_t *buf8) 961 { 962 if (buf8[NFP_ELF_EI_CLASS] != NFP_ELF_ELFCLASS64) 963 return -EINVAL; 964 965 return 0; 966 } 967 968 static struct nfp_elf * 969 nfp_elf_mutable_buf(void *buf, 970 size_t buf_len) 971 { 972 int err = 0; 973 uint8_t *buf8 = buf; 974 struct nfp_elf *ectx; 975 976 if (buf == NULL) { 977 PMD_DRV_LOG(ERR, "Invalid parameters."); 978 return NULL; 979 } 980 981 if (buf_len < sizeof(struct nfp_elf_elf64_ehdr)) { 982 PMD_DRV_LOG(ERR, "ELF data too short."); 983 return NULL; 984 } 985 986 ectx = calloc(1, sizeof(struct nfp_elf)); 987 if (ectx == NULL) { 988 PMD_DRV_LOG(ERR, "Out of memory."); 989 return NULL; 990 } 991 992 ectx->rev_min = -1; 993 ectx->rev_max = -1; 994 ectx->mip_sh_off = UINT64_MAX; 995 996 err = nfp_elf_is_valid_file(buf8); 997 if (err != 0) { 998 PMD_DRV_LOG(ERR, "Not a valid ELF file."); 999 goto elf_free; 1000 } 1001 1002 err = nfp_elf_is_valid_class(buf8); 1003 if (err != 0) { 1004 PMD_DRV_LOG(ERR, "Unknown ELF class."); 1005 goto elf_free; 1006 } 1007 1008 err = nfp_elf_read_file_headers(ectx, buf); 1009 if (err != 0) { 1010 PMD_DRV_LOG(ERR, "Failed to read file headers."); 1011 goto elf_free; 1012 } 1013 1014 err = nfp_elf_read_section_headers(ectx, buf8, buf_len); 1015 if (err != 0) { 1016 PMD_DRV_LOG(ERR, "Failed to read section headers."); 1017 goto elf_free; 1018 } 1019 1020 err = nfp_elf_read_shstrtab(ectx); 1021 if (err != 0) { 1022 PMD_DRV_LOG(ERR, "Failed to read shstrtab."); 1023 goto elf_free; 1024 } 1025 1026 /* Read first symtab if any, assuming it's the primary or only one */ 1027 err = nfp_elf_read_first_symtab(ectx); 1028 if (err != 0) { 1029 PMD_DRV_LOG(ERR, "Failed to read first symtab."); 1030 goto elf_free; 1031 } 1032 1033 /* Populate the fw_mip struct if we have a .note for it */ 1034 if (ectx->mip_shndx != 0) { 1035 err = nfp_elf_populate_fw_mip(ectx, buf8); 1036 if (err != 0) { 1037 PMD_DRV_LOG(ERR, "Failed to populate the fw mip."); 1038 goto elf_free; 1039 } 1040 } 1041 1042 ectx->_buf = buf; 1043 ectx->_bufsz = 0; 1044 1045 return ectx; 1046 1047 elf_free: 1048 nfp_elf_free(ectx); 1049 1050 return NULL; 1051 } 1052 1053 int 1054 nfp_elf_get_fw_version(uint32_t *fw_version, 1055 char *fw_name) 1056 { 1057 void *fw_buf; 1058 size_t fsize; 1059 struct nfp_elf *elf; 1060 1061 if (rte_firmware_read(fw_name, &fw_buf, &fsize) != 0) { 1062 PMD_DRV_LOG(ERR, "firmware %s not found!", fw_name); 1063 return -ENOENT; 1064 } 1065 1066 elf = nfp_elf_mutable_buf(fw_buf, fsize); 1067 if (elf == NULL) { 1068 PMD_DRV_LOG(ERR, "Parse nffw file failed."); 1069 free(fw_buf); 1070 return -EIO; 1071 } 1072 1073 *fw_version = rte_le_to_cpu_32(elf->fw_mip.fw_version); 1074 1075 nfp_elf_free(elf); 1076 free(fw_buf); 1077 return 0; 1078 } 1079 1080