| 458 | } |
| 459 | |
| 460 | static ssize_t relocate_remaining_items(void *fsp, size_t size, |
| 461 | uintptr_t new_addr, size_t fih_offset) |
| 462 | { |
| 463 | EFI_FFS_FILE_HEADER *ffsfh; |
| 464 | EFI_COMMON_SECTION_HEADER *csh; |
| 465 | FSP_INFO_HEADER *fih; |
| 466 | ssize_t adjustment; |
| 467 | size_t offset; |
| 468 | |
| 469 | printk(FSP_DBG_LVL, "FSP_INFO_HEADER offset is %zx\n", fih_offset); |
| 470 | |
| 471 | if (fih_offset == 0) { |
| 472 | printk(BIOS_ERR, "FSP_INFO_HEADER offset is 0.\n"); |
| 473 | return -1; |
| 474 | } |
| 475 | |
| 476 | /* FSP_INFO_HEADER at first file in FV within first RAW section. */ |
| 477 | ffsfh = relative_offset(fsp, fih_offset); |
| 478 | fih_offset += file_section_offset(ffsfh); |
| 479 | csh = relative_offset(fsp, fih_offset); |
| 480 | fih_offset += section_data_offset(csh); |
| 481 | fih = relative_offset(fsp, fih_offset); |
| 482 | |
| 483 | if (guid_compare(&ffsfh->Name, &fih_guid)) { |
| 484 | printk(BIOS_ERR, "Bad FIH GUID.\n"); |
| 485 | return -1; |
| 486 | } |
| 487 | |
| 488 | if (read_le8(&csh->Type) != EFI_SECTION_RAW) { |
| 489 | printk(BIOS_ERR, "FIH file should have raw section: %x\n", |
| 490 | read_le8(&csh->Type)); |
| 491 | return -1; |
| 492 | } |
| 493 | |
| 494 | if (read_le32(&fih->Signature) != FSP_SIG) { |
| 495 | printk(BIOS_ERR, "Unexpected FIH signature: %08x\n", |
| 496 | read_le32(&fih->Signature)); |
| 497 | } |
| 498 | |
| 499 | adjustment = (intptr_t)new_addr - read_le32(&fih->ImageBase); |
| 500 | |
| 501 | /* Update ImageBase to reflect FSP's new home. */ |
| 502 | write_le32(&fih->ImageBase, adjustment + read_le32(&fih->ImageBase)); |
| 503 | printk(FSP_DBG_LVL, "Updated FSP InfoHdr Image Base to %x\n", |
| 504 | read_le32(&fih->ImageBase)); |
| 505 | |
| 506 | /* Need to find patch table and adjust each entry. The tables |
| 507 | * following FSP_INFO_HEADER have a 32-bit signature and header |
| 508 | * length. The patch table is denoted as having a 'FSPP' signature; |
| 509 | * the table format doesn't follow the other tables. */ |
| 510 | offset = fih_offset + read_le32(&fih->HeaderLength); |
| 511 | while (offset + 2 * sizeof(uint32_t) <= size) { |
| 512 | uint32_t *table_headers; |
| 513 | |
| 514 | table_headers = relative_offset(fsp, offset); |
| 515 | |
| 516 | printk(FSP_DBG_LVL, "Checking offset %zx for 'FSPP'\n", |
| 517 | offset); |
no test coverage detected