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(const char *strtab, 328 ssize_t tab_sz, 329 const char *key) 330 { 331 size_t s_len; 332 const char *s; 333 size_t key_len = strlen(key); 334 335 if (strtab == NULL) 336 return NULL; 337 338 for (s = strtab, s_len = strlen(s) + 1; 339 (s[0] != '\0') && (tab_sz > 0); 340 s_len = strlen(s) + 1, tab_sz -= s_len, s += s_len) { 341 if ((strncmp(s, key, key_len) == 0) && (s[key_len] == '=')) 342 return &s[key_len + 1]; 343 } 344 345 return NULL; 346 } 347 348 static bool 349 nfp_elf_arch_is_thornham(struct nfp_elf *ectx) 350 { 351 if (ectx == NULL) 352 return false; 353 354 if (ectx->family == NFP_CHIP_FAMILY_NFP6000 || ectx->family == NFP_CHIP_FAMILY_NFP3800) 355 return true; 356 357 return false; 358 } 359 360 static int 361 nfp_elf_parse_sht_rel(struct nfp_elf_elf64_shdr *sec, 362 struct nfp_elf *ectx, 363 size_t idx, 364 uint8_t *buf8) 365 { 366 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 367 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 368 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 369 370 if (sh_entsize != sizeof(struct nfp_elf_elf64_rel)) { 371 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 372 return -EINVAL; 373 } 374 375 if (!nfp_elf_check_sh_size(sh_size)) { 376 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 377 return -EINVAL; 378 } 379 380 ectx->shdrs_data[idx] = buf8 + sh_offset; 381 ectx->shdrs_host_endian[idx] = 1; 382 383 return 0; 384 } 385 386 static int 387 nfp_elf_parse_note_name_nfp(struct nfp_elf *ectx, 388 size_t idx, 389 uint32_t ndescsz, 390 uint32_t ntype, 391 const char *nname, 392 rte_le32_t *descword) 393 { 394 if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP, NFP_ELT_NOTE_NAME_NFP_SZ) == 0) { 395 switch (ntype) { 396 case NFP_ELF_NT_NFP_REVS: 397 if (ndescsz != 8) { 398 PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); 399 return -EINVAL; 400 } 401 402 ectx->rev_min = (int)rte_le_to_cpu_32(descword[0]); 403 ectx->rev_max = (int)rte_le_to_cpu_32(descword[1]); 404 break; 405 case NFP_ELF_NT_NFP_MIP_LOCATION: 406 if (ndescsz != 12) { 407 PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); 408 return -EINVAL; 409 } 410 411 ectx->mip_shndx = rte_le_to_cpu_32(descword[0]); 412 if (ectx->mip_shndx == 0) { 413 ectx->mip_sh_off = 0; 414 break; 415 } 416 417 if (ectx->mip_shndx >= ectx->shdrs_cnt) { 418 PMD_DRV_LOG(ERR, "Invalid ELF NOTE shndx in section %zu.", idx); 419 return -EINVAL; 420 } 421 422 ectx->mip_sh_off = rte_le_to_cpu_32(descword[1]) | 423 (uint64_t)rte_le_to_cpu_32(descword[2]) << 32; 424 break; 425 default: 426 break; 427 } 428 } else if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, 429 NFP_ELT_NOTE_NAME_NFP_USER_SZ) == 0 && ntype == NFP_ELF_NT_NFP_USER) { 430 ectx->user_note_cnt++; 431 } 432 433 return 0; 434 } 435 436 static int 437 nfp_elf_parse_sht_note(struct nfp_elf_elf64_shdr *sec, 438 struct nfp_elf *ectx, 439 size_t idx, 440 uint8_t *buf8) 441 { 442 int err; 443 size_t nsz; 444 uint8_t *desc; 445 uint32_t ntype; 446 uint32_t nnamesz; 447 uint32_t ndescsz; 448 const char *nname; 449 uint8_t *shdrs_data; 450 rte_le32_t *descword; 451 struct nfp_elf_elf64_nhdr *nhdr; 452 struct nfp_elf_user_note *unote; 453 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 454 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 455 456 if (!nfp_elf_check_sh_size(sh_size)) { 457 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 458 return -EINVAL; 459 } 460 461 shdrs_data = buf8 + sh_offset; 462 ectx->shdrs_data[idx] = shdrs_data; 463 ectx->shdrs_host_endian[idx] = 0; 464 465 /* Extract notes that we recognise */ 466 nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; 467 468 while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { 469 nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); 470 ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); 471 ntype = rte_le_to_cpu_32(nhdr->n_type); 472 nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); 473 descword = (rte_le32_t *)((uint8_t *)nhdr + sizeof(*nhdr) + 474 ((nnamesz + UINT32_C(3)) & ~UINT32_C(3))); 475 476 err = nfp_elf_parse_note_name_nfp(ectx, idx, ndescsz, ntype, nname, descword); 477 if (err != 0) 478 return err; 479 480 nhdr = (struct nfp_elf_elf64_nhdr *)((uint8_t *)descword + 481 ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); 482 } 483 484 if (ectx->user_note_cnt == 0) 485 return 0; 486 487 ectx->user_notes = calloc(ectx->user_note_cnt, sizeof(*ectx->user_notes)); 488 if (ectx->user_notes == NULL) { 489 PMD_DRV_LOG(ERR, "Out of memory."); 490 return -ENOMEM; 491 } 492 493 nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; 494 unote = ectx->user_notes; 495 while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { 496 nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); 497 ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); 498 ntype = rte_le_to_cpu_32(nhdr->n_type); 499 nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); 500 desc = (uint8_t *)nhdr + sizeof(*nhdr) + 501 ((nnamesz + UINT32_C(3)) & ~UINT32_C(3)); 502 503 if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, 504 NFP_ELT_NOTE_NAME_NFP_USER_SZ) != 0) 505 continue; 506 507 if (ntype != NFP_ELF_NT_NFP_USER) 508 continue; 509 510 unote->name = (const char *)desc; 511 nsz = strlen(unote->name) + 1; 512 if (nsz % 4 != 0) 513 nsz = ((nsz / 4) + 1) * 4; 514 if (nsz > ndescsz) { 515 PMD_DRV_LOG(ERR, "Invalid ELF USER NOTE descsz in section %zu.", idx); 516 return -EINVAL; 517 } 518 519 unote->data_sz = ndescsz - (uint32_t)nsz; 520 if (unote->data_sz != 0) 521 unote->data = desc + nsz; 522 unote++; 523 524 nhdr = (struct nfp_elf_elf64_nhdr *) 525 (desc + ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); 526 } 527 528 return 0; 529 } 530 531 static int 532 nfp_elf_parse_sht_meconfig(struct nfp_elf_elf64_shdr *sec, 533 struct nfp_elf *ectx, 534 size_t idx, 535 uint8_t *buf8) 536 { 537 size_t ent_cnt; 538 uint8_t *shdrs_data; 539 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 540 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 541 542 if (!nfp_elf_check_sh_size(sh_size)) { 543 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 544 return -EINVAL; 545 } 546 547 shdrs_data = buf8 + sh_offset; 548 ent_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); 549 ectx->shdrs_data[idx] = shdrs_data; 550 ectx->meconfs = (struct nfp_elf_elf_meconfig *)shdrs_data; 551 ectx->meconfs_cnt = ent_cnt; 552 ectx->shdrs_host_endian[idx] = 1; 553 554 return 0; 555 } 556 557 static int 558 nfp_elf_parse_sht_initreg(struct nfp_elf_elf64_shdr *sec, 559 struct nfp_elf *ectx, 560 size_t idx, 561 uint8_t *buf8) 562 { 563 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 564 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 565 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 566 567 if (!nfp_elf_arch_is_thornham(ectx)) { 568 PMD_DRV_LOG(ERR, "Section not supported for target arch."); 569 return -ENOTSUP; 570 } 571 572 if (sh_entsize != sizeof(struct nfp_elf_elf_initregentry) || 573 !nfp_elf_check_sh_size(sh_size)) { 574 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 575 return -EINVAL; 576 } 577 578 ectx->shdrs_data[idx] = buf8 + sh_offset; 579 ectx->shdrs_host_endian[idx] = 1; 580 581 return 0; 582 } 583 584 static int 585 nfp_elf_parse_sht_symtab(struct nfp_elf_elf64_shdr *sec, 586 struct nfp_elf *ectx, 587 size_t idx, 588 uint8_t *buf8) 589 { 590 uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); 591 uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); 592 uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 593 594 if (sh_entsize != sizeof(struct nfp_elf_elf64_sym) || 595 !nfp_elf_check_sh_size(sh_size)) { 596 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 597 return -EINVAL; 598 } 599 600 ectx->shdrs_data[idx] = buf8 + sh_offset; 601 ectx->shdrs_host_endian[ectx->shdr_idx_symtab] = 1; 602 603 return 0; 604 } 605 606 static int 607 nfp_elf_populate_fw_mip(struct nfp_elf *ectx, 608 uint8_t *buf8) 609 { 610 uint8_t *pu8; 611 const char *nx; 612 ssize_t tab_sz; 613 uint64_t sh_size; 614 const char *str_tab; 615 uint64_t sh_offset; 616 uint32_t first_entry; 617 const struct nfp_mip *mip; 618 struct nfp_elf_elf64_shdr *sec; 619 const struct nfp_mip_entry *ent; 620 const struct nfp_mip_fwinfo_entry *fwinfo; 621 622 sec = &ectx->shdrs[ectx->mip_shndx]; 623 sh_size = rte_le_to_cpu_64(sec->sh_size); 624 sh_offset = rte_le_to_cpu_64(sec->sh_offset); 625 pu8 = buf8 + sh_offset + ectx->mip_sh_off; 626 mip = (const struct nfp_mip *)pu8; 627 first_entry = rte_le_to_cpu_32(mip->first_entry); 628 629 if (mip->signature != NFP_MIP_SIGNATURE) { 630 PMD_DRV_LOG(ERR, "Incorrect MIP signature %#08x.", 631 rte_le_to_cpu_32(mip->signature)); 632 return -EINVAL; 633 } 634 635 ectx->fw_mip.shndx = ectx->mip_shndx; 636 ectx->fw_mip.sh_offset = ectx->mip_sh_off; 637 ectx->fw_mip.mip_ver = mip->mip_version; 638 639 if (ectx->fw_mip.mip_ver != NFP_MIP_VERSION) { 640 PMD_DRV_LOG(ERR, "MIP note pointer does not point to recognised version."); 641 return -EINVAL; 642 } 643 644 ectx->fw_mip.fw_version = mip->version; 645 ectx->fw_mip.fw_buildnum = mip->buildnum; 646 ectx->fw_mip.fw_buildtime = mip->buildtime; 647 strncpy(ectx->fw_mip.fw_name, mip->name, 16); 648 649 /* 650 * If there is a FWINFO v1 entry, it will be first and 651 * right after the MIP itself, so in the same section. 652 */ 653 if (ectx->mip_sh_off + first_entry + sizeof(*ent) < sh_size) { 654 pu8 += first_entry; 655 ent = (const struct nfp_mip_entry *)pu8; 656 if (ent->type == NFP_MIP_TYPE_FWINFO && ent->version == 1) { 657 pu8 += sizeof(*ent); 658 fwinfo = (const struct nfp_mip_fwinfo_entry *)pu8; 659 if (fwinfo->kv_len != 0) { 660 ectx->fw_info_strtab_sz = fwinfo->kv_len; 661 ectx->fw_info_strtab = fwinfo->key_value_strs; 662 } 663 } 664 } 665 666 str_tab = ectx->fw_info_strtab; 667 tab_sz = (ssize_t)ectx->fw_info_strtab_sz; 668 ectx->fw_mip.fw_typeid = nfp_elf_fwinfo_lookup(str_tab, tab_sz, "TypeId"); 669 670 /* 671 * TypeId will be the last reserved key-value pair, so skip 672 * to the first entry after it for the user values. 673 */ 674 if (ectx->fw_mip.fw_typeid == NULL) 675 return 0; 676 677 nx = nfp_elf_fwinfo_next(ectx, ectx->fw_mip.fw_typeid); 678 if (nx == NULL) 679 ectx->fw_info_strtab_sz = 0; 680 else 681 ectx->fw_info_strtab_sz -= (nx - ectx->fw_info_strtab); 682 ectx->fw_info_strtab = nx; 683 684 return 0; 685 } 686 687 static int 688 nfp_elf_read_file_headers(struct nfp_elf *ectx, 689 void *buf) 690 { 691 uint16_t e_type; 692 uint32_t e_flags; 693 uint32_t e_version; 694 uint16_t e_machine; 695 696 ectx->ehdr = buf; 697 e_type = rte_le_to_cpu_16(ectx->ehdr->e_type); 698 e_flags = rte_le_to_cpu_32(ectx->ehdr->e_flags); 699 e_version = rte_le_to_cpu_32(ectx->ehdr->e_version); 700 e_machine = rte_le_to_cpu_16(ectx->ehdr->e_machine); 701 702 switch (e_machine) { 703 case NFP_ELF_EM_NFP: 704 ectx->family = (e_flags >> NFP_ELF_EF_NFP_FAMILY_LSB) 705 & NFP_ELF_EF_NFP_FAMILY_MASK; 706 break; 707 case NFP_ELF_EM_NFP6000: 708 ectx->family = NFP_CHIP_FAMILY_NFP6000; 709 break; 710 default: 711 PMD_DRV_LOG(ERR, "Invalid ELF machine type."); 712 return -EINVAL; 713 } 714 715 if ((e_type != NFP_ELF_ET_EXEC && e_type != NFP_ELF_ET_REL && 716 e_type != NFP_ELF_ET_NFP_PARTIAL_EXEC && 717 e_type != NFP_ELF_ET_NFP_PARTIAL_REL) || 718 e_version != NFP_ELF_EV_CURRENT || 719 ectx->ehdr->e_ehsize != sizeof(struct nfp_elf_elf64_ehdr) || 720 ectx->ehdr->e_shentsize != sizeof(struct nfp_elf_elf64_shdr)) { 721 PMD_DRV_LOG(ERR, "Invalid ELF file header."); 722 return -EINVAL; 723 } 724 725 if (ectx->ehdr->e_shoff < ectx->ehdr->e_ehsize) { 726 PMD_DRV_LOG(ERR, "Invalid ELF header content."); 727 return -EINVAL; 728 } 729 730 if (ectx->ehdr->e_shstrndx >= ectx->ehdr->e_shnum) { 731 PMD_DRV_LOG(ERR, "Invalid ELF header content."); 732 return -EINVAL; 733 } 734 735 return 0; 736 } 737 738 static int 739 nfp_elf_read_section_headers(struct nfp_elf *ectx, 740 uint8_t *buf8, 741 size_t buf_len) 742 { 743 size_t idx; 744 int err = 0; 745 uint8_t *pu8; 746 uint64_t sh_size; 747 uint64_t sh_offset; 748 uint64_t sh_entsize; 749 struct nfp_elf_elf64_shdr *sec; 750 uint64_t e_shoff = rte_le_to_cpu_16(ectx->ehdr->e_shoff); 751 uint16_t e_shnum = rte_le_to_cpu_16(ectx->ehdr->e_shnum); 752 753 if (buf_len < e_shoff + ((size_t)e_shnum * sizeof(*sec))) { 754 PMD_DRV_LOG(ERR, "ELF data too short."); 755 return -EINVAL; 756 } 757 758 pu8 = buf8 + e_shoff; 759 760 if (e_shnum == 0) { 761 ectx->shdrs = NULL; 762 ectx->shdrs_data = NULL; 763 ectx->shdrs_host_endian = NULL; 764 ectx->shdrs_cnt = 0; 765 return 0; 766 } 767 768 ectx->shdrs = calloc(e_shnum, sizeof(*ectx->shdrs)); 769 if (ectx->shdrs == NULL) { 770 PMD_DRV_LOG(ERR, "Out of memory."); 771 return -ENOMEM; 772 } 773 774 ectx->shdrs_data = calloc(e_shnum, sizeof(void *)); 775 if (ectx->shdrs_data == NULL) { 776 PMD_DRV_LOG(ERR, "Out of memory."); 777 err = -ENOMEM; 778 goto free_shdrs; 779 } 780 781 ectx->shdrs_host_endian = calloc(e_shnum, sizeof(ectx->shdrs_host_endian[0])); 782 if (ectx->shdrs_host_endian == NULL) { 783 PMD_DRV_LOG(ERR, "Out of memory."); 784 err = -ENOMEM; 785 goto free_shdrs_data; 786 } 787 788 memcpy(ectx->shdrs, pu8, e_shnum * sizeof(*ectx->shdrs)); 789 ectx->shdrs_cnt = e_shnum; 790 791 for (idx = 0, sec = ectx->shdrs; idx < ectx->shdrs_cnt; idx++, sec++) { 792 sh_size = rte_le_to_cpu_64(sec->sh_size); 793 sh_offset = rte_le_to_cpu_64(sec->sh_offset); 794 sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); 795 796 if (sh_entsize != 0 && (sh_size % sh_entsize != 0)) { 797 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 798 err = -EINVAL; 799 goto free_shdrs_host_endian; 800 } 801 802 switch (rte_le_to_cpu_32(sec->sh_type)) { 803 case NFP_ELF_SHT_REL: 804 err = nfp_elf_parse_sht_rel(sec, ectx, idx, buf8); 805 if (err != 0) { 806 PMD_DRV_LOG(ERR, "Failed to parse sht rel."); 807 goto free_shdrs_host_endian; 808 } 809 break; 810 case NFP_ELF_SHT_NOTE: 811 err = nfp_elf_parse_sht_note(sec, ectx, idx, buf8); 812 if (err != 0) { 813 PMD_DRV_LOG(ERR, "Failed to parse sht note."); 814 goto free_shdrs_host_endian; 815 } 816 break; 817 case NFP_ELF_SHT_NFP_MECONFIG: 818 err = nfp_elf_parse_sht_meconfig(sec, ectx, idx, buf8); 819 if (err != 0) { 820 PMD_DRV_LOG(ERR, "Failed to parse sht meconfig."); 821 goto free_shdrs_host_endian; 822 } 823 break; 824 case NFP_ELF_SHT_NFP_INITREG: 825 err = nfp_elf_parse_sht_initreg(sec, ectx, idx, buf8); 826 if (err != 0) { 827 PMD_DRV_LOG(ERR, "Failed to parse sht initregp."); 828 goto free_shdrs_host_endian; 829 } 830 break; 831 case NFP_ELF_SHT_SYMTAB: 832 err = nfp_elf_parse_sht_symtab(sec, ectx, idx, buf8); 833 if (err != 0) { 834 PMD_DRV_LOG(ERR, "Failed to parse sht symtab."); 835 goto free_shdrs_host_endian; 836 } 837 break; 838 case NFP_ELF_SHT_NOBITS: 839 case NFP_ELF_SHT_NULL: 840 break; 841 default: 842 if (sh_offset > 0 && sh_size <= 0) 843 break; 844 845 /* 846 * Limit sections to 4GiB, because they won't need to be this large 847 * and this ensures we can handle the file on 32-bit hosts without 848 * unexpected problems. 849 */ 850 if (sh_size > UINT32_MAX) { 851 PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); 852 err = -EINVAL; 853 goto free_shdrs_host_endian; 854 } 855 856 pu8 = buf8 + sh_offset; 857 ectx->shdrs_data[idx] = pu8; 858 ectx->shdrs_host_endian[idx] = 0; 859 break; 860 } 861 } 862 863 return 0; 864 865 free_shdrs_host_endian: 866 free(ectx->shdrs_host_endian); 867 free_shdrs_data: 868 free(ectx->shdrs_data); 869 free_shdrs: 870 free(ectx->shdrs); 871 872 return err; 873 } 874 875 static int 876 nfp_elf_read_shstrtab(struct nfp_elf *ectx) 877 { 878 struct nfp_elf_elf64_shdr *sec; 879 uint16_t e_shstrndx = rte_le_to_cpu_16(ectx->ehdr->e_shstrndx); 880 881 if (ectx->ehdr->e_shnum <= ectx->ehdr->e_shstrndx) { 882 PMD_DRV_LOG(ERR, "Invalid Index."); 883 return -EINVAL; 884 } 885 886 sec = &ectx->shdrs[e_shstrndx]; 887 if (sec == NULL || rte_le_to_cpu_32(sec->sh_type) != NFP_ELF_SHT_STRTAB) { 888 PMD_DRV_LOG(ERR, "Invalid ELF shstrtab."); 889 return -EINVAL; 890 } 891 892 ectx->shstrtab = ectx->shdrs_data[e_shstrndx]; 893 ectx->shstrtab_sz = rte_le_to_cpu_64(sec->sh_size); 894 895 return 0; 896 } 897 898 static int 899 nfp_elf_read_first_symtab(struct nfp_elf *ectx) 900 { 901 size_t idx; 902 uint32_t sh_type; 903 uint64_t sh_size; 904 struct nfp_elf_elf64_shdr *sec = NULL; 905 906 for (idx = 0; idx < ectx->shdrs_cnt; idx++) { 907 sec = &ectx->shdrs[idx]; 908 if (sec != NULL) { 909 sh_type = rte_le_to_cpu_32(sec->sh_type); 910 if (sh_type == NFP_ELF_SHT_SYMTAB) 911 break; 912 } 913 } 914 915 if (sec == NULL) 916 return -EINVAL; 917 918 sh_size = rte_le_to_cpu_64(sec->sh_size); 919 920 if (idx < ectx->shdrs_cnt && sh_type == NFP_ELF_SHT_SYMTAB) { 921 ectx->shdr_idx_symtab = idx; 922 ectx->syms = ectx->shdrs_data[idx]; 923 ectx->syms_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); 924 925 /* Load symtab's strtab */ 926 idx = rte_le_to_cpu_32(sec->sh_link); 927 928 if (idx == NFP_ELF_SHN_UNDEF || idx >= ectx->shdrs_cnt) { 929 PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); 930 return -EINVAL; 931 } 932 933 sec = &ectx->shdrs[idx]; 934 sh_type = rte_le_to_cpu_32(sec->sh_type); 935 if (sh_type != NFP_ELF_SHT_STRTAB) { 936 PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); 937 return -EINVAL; 938 } 939 940 if (!nfp_elf_check_sh_size(sh_size)) { 941 PMD_DRV_LOG(ERR, "ELF symtab has invalid strtab."); 942 return -EINVAL; 943 } 944 945 ectx->symstrtab = ectx->shdrs_data[idx]; 946 ectx->symstrtab_sz = sh_size; 947 } 948 949 return 0; 950 } 951 952 static int 953 nfp_elf_is_valid_file(uint8_t *buf8) 954 { 955 if (buf8[NFP_ELF_EI_MAG0] != NFP_ELF_ELFMAG0 || 956 buf8[NFP_ELF_EI_MAG1] != NFP_ELF_ELFMAG1 || 957 buf8[NFP_ELF_EI_MAG2] != NFP_ELF_ELFMAG2 || 958 buf8[NFP_ELF_EI_MAG3] != NFP_ELF_ELFMAG3 || 959 buf8[NFP_ELF_EI_VERSION] != NFP_ELF_EV_CURRENT || 960 buf8[NFP_ELF_EI_DATA] != NFP_ELF_ELFDATA2LSB) 961 return -EINVAL; 962 963 return 0; 964 } 965 966 static int 967 nfp_elf_is_valid_class(uint8_t *buf8) 968 { 969 if (buf8[NFP_ELF_EI_CLASS] != NFP_ELF_ELFCLASS64) 970 return -EINVAL; 971 972 return 0; 973 } 974 975 static struct nfp_elf * 976 nfp_elf_mutable_buf(void *buf, 977 size_t buf_len) 978 { 979 int err = 0; 980 uint8_t *buf8 = buf; 981 struct nfp_elf *ectx; 982 983 if (buf == NULL) { 984 PMD_DRV_LOG(ERR, "Invalid parameters."); 985 return NULL; 986 } 987 988 if (buf_len < sizeof(struct nfp_elf_elf64_ehdr)) { 989 PMD_DRV_LOG(ERR, "ELF data too short."); 990 return NULL; 991 } 992 993 ectx = calloc(1, sizeof(struct nfp_elf)); 994 if (ectx == NULL) { 995 PMD_DRV_LOG(ERR, "Out of memory."); 996 return NULL; 997 } 998 999 ectx->rev_min = -1; 1000 ectx->rev_max = -1; 1001 ectx->mip_sh_off = UINT64_MAX; 1002 1003 err = nfp_elf_is_valid_file(buf8); 1004 if (err != 0) { 1005 PMD_DRV_LOG(ERR, "Not a valid ELF file."); 1006 goto elf_free; 1007 } 1008 1009 err = nfp_elf_is_valid_class(buf8); 1010 if (err != 0) { 1011 PMD_DRV_LOG(ERR, "Unknown ELF class."); 1012 goto elf_free; 1013 } 1014 1015 err = nfp_elf_read_file_headers(ectx, buf); 1016 if (err != 0) { 1017 PMD_DRV_LOG(ERR, "Failed to read file headers."); 1018 goto elf_free; 1019 } 1020 1021 err = nfp_elf_read_section_headers(ectx, buf8, buf_len); 1022 if (err != 0) { 1023 PMD_DRV_LOG(ERR, "Failed to read section headers."); 1024 goto elf_free; 1025 } 1026 1027 err = nfp_elf_read_shstrtab(ectx); 1028 if (err != 0) { 1029 PMD_DRV_LOG(ERR, "Failed to read shstrtab."); 1030 goto elf_free; 1031 } 1032 1033 /* Read first symtab if any, assuming it's the primary or only one */ 1034 err = nfp_elf_read_first_symtab(ectx); 1035 if (err != 0) { 1036 PMD_DRV_LOG(ERR, "Failed to read first symtab."); 1037 goto elf_free; 1038 } 1039 1040 /* Populate the fw_mip struct if we have a .note for it */ 1041 if (ectx->mip_shndx != 0) { 1042 err = nfp_elf_populate_fw_mip(ectx, buf8); 1043 if (err != 0) { 1044 PMD_DRV_LOG(ERR, "Failed to populate the fw mip."); 1045 goto elf_free; 1046 } 1047 } 1048 1049 ectx->_buf = buf; 1050 ectx->_bufsz = 0; 1051 1052 return ectx; 1053 1054 elf_free: 1055 nfp_elf_free(ectx); 1056 1057 return NULL; 1058 } 1059 1060 int 1061 nfp_elf_get_fw_version(uint32_t *fw_version, 1062 char *fw_name) 1063 { 1064 void *fw_buf; 1065 size_t fsize; 1066 struct nfp_elf *elf; 1067 1068 if (rte_firmware_read(fw_name, &fw_buf, &fsize) != 0) { 1069 PMD_DRV_LOG(ERR, "Firmware %s not found!", fw_name); 1070 return -ENOENT; 1071 } 1072 1073 elf = nfp_elf_mutable_buf(fw_buf, fsize); 1074 if (elf == NULL) { 1075 PMD_DRV_LOG(ERR, "Parse nffw file failed."); 1076 free(fw_buf); 1077 return -EIO; 1078 } 1079 1080 *fw_version = rte_le_to_cpu_32(elf->fw_mip.fw_version); 1081 1082 nfp_elf_free(elf); 1083 free(fw_buf); 1084 return 0; 1085 } 1086 1087