1 /*++ 2 3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 GenFvImageLib.c 15 16 Abstract: 17 18 This file contains functions required to generate a Firmware Volume. 19 20 --*/ 21 22 // 23 // Include files 24 // 25 #include "GenFvImageLib.h" 26 #include "GenFvImageLibInternal.h" 27 #include <string.h> 28 #include EFI_GUID_DEFINITION (PeiPeCoffLoader) 29 #include "EfiFirmwareFileSystem.h" 30 #include "EfiWorkingBlockHeader.h" 31 #include "EfiVariable.h" 32 #include <io.h> 33 #include <assert.h> 34 #include "CommonLib.h" 35 #include "FvLib.h" 36 #include "EfiImage.h" 37 #include "crc32.h" 38 #include "EfiUtilityMsgs.h" 39 #include EFI_GUID_DEFINITION (FirmwareFileSystem) 40 #include EFI_GUID_DEFINITION (FirmwareFileSystem2) 41 42 // 43 // Define the PE/COFF loader 44 // 45 extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader; 46 47 // 48 // Local function prototypes 49 // 50 EFI_STATUS 51 GetPe32Info ( 52 IN UINT8 *Pe32, 53 OUT UINT32 *EntryPoint, 54 OUT UINT32 *BaseOfCode, 55 OUT UINT16 *MachineType 56 ); 57 58 // 59 // Local function implementations. 60 // 61 #if (PI_SPECIFICATION_VERSION < 0x00010000) 62 EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; 63 #else 64 EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID; 65 #endif 66 67 EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f }; 68 69 // 70 // This data array will be located at the base of the Firmware Volume Header (FVH) 71 // in the boot block. It must not exceed 14 bytes of code. The last 2 bytes 72 // will be used to keep the FVH checksum consistent. 73 // This code will be run in response to a starutp IPI for HT-enabled systems. 74 // 75 #define SIZEOF_STARTUP_DATA_ARRAY 0x10 76 77 UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { 78 // 79 // EA D0 FF 00 F0 ; far jmp F000:FFD0 80 // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes 81 // 0, 0 ; Checksum Padding 82 // 83 0xEA, 84 0xD0, 85 0xFF, 86 0x0, 87 0xF0, 88 0x00, 89 0x00, 90 0x00, 91 0x00, 92 0x00, 93 0x00, 94 0x00, 95 0x00, 96 0x00, 97 0x00, 98 0x00 99 }; 100 101 UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { 102 // 103 // EB CE ; jmp short ($-0x30) 104 // ; (from offset 0x0 to offset 0xFFD0) 105 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes 106 // 0, 0 ; Checksum Padding 107 // 108 0xEB, 109 0xCE, 110 0x00, 111 0x00, 112 0x00, 113 0x00, 114 0x00, 115 0x00, 116 0x00, 117 0x00, 118 0x00, 119 0x00, 120 0x00, 121 0x00, 122 0x00, 123 0x00 124 }; 125 126 EFI_STATUS 127 ParseFvInf ( 128 IN MEMORY_FILE *InfFile, 129 IN FV_INFO *FvInfo 130 ) 131 /*++ 132 133 Routine Description: 134 135 This function parses a FV.INF file and copies info into a FV_INFO structure. 136 137 Arguments: 138 139 InfFile Memory file image. 140 FvInfo Information read from INF file. 141 142 Returns: 143 144 EFI_SUCCESS INF file information successfully retrieved. 145 EFI_ABORTED INF file has an invalid format. 146 EFI_NOT_FOUND A required string was not found in the INF file. 147 --*/ 148 { 149 CHAR8 Value[_MAX_PATH]; 150 UINT64 Value64; 151 UINTN Index; 152 EFI_STATUS Status; 153 154 // 155 // Initialize FV info 156 // 157 memset (FvInfo, 0, sizeof (FV_INFO)); 158 159 // 160 // Read the FV base address 161 // 162 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value); 163 164 if (Status == EFI_SUCCESS) { 165 // 166 // Get the base address 167 // 168 Status = AsciiStringToUint64 (Value, FALSE, &Value64); 169 if (EFI_ERROR (Status)) { 170 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value"); 171 return EFI_ABORTED; 172 } 173 174 FvInfo->BaseAddress = Value64; 175 } else { 176 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value"); 177 return EFI_ABORTED; 178 } 179 // 180 // Read the FV Guid 181 // 182 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value); 183 184 if (Status == EFI_SUCCESS) { 185 // 186 // Get the guid value 187 // 188 Status = StringToGuid (Value, &FvInfo->FvGuid); 189 if (EFI_ERROR (Status)) { 190 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); 191 } 192 } else { 193 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); 194 } 195 // 196 // Read the FV file name 197 // 198 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value); 199 200 if (Status == EFI_SUCCESS) { 201 // 202 // copy the file name 203 // 204 strcpy (FvInfo->FvName, Value); 205 } else { 206 Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified"); 207 return EFI_ABORTED; 208 } 209 // 210 // Read the Sym file name 211 // 212 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value); 213 214 if (Status == EFI_SUCCESS) { 215 // 216 // copy the file name 217 // 218 strcpy (FvInfo->SymName, Value); 219 } else { 220 // 221 // Symbols not required, so init to NULL. 222 // 223 strcpy (FvInfo->SymName, ""); 224 } 225 // 226 // Read the read disabled capability attribute 227 // 228 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value); 229 230 if (Status == EFI_SUCCESS) { 231 // 232 // Update the read disabled flag 233 // 234 if (strcmp (Value, TRUE_STRING) == 0) { 235 FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP; 236 } else if (strcmp (Value, FALSE_STRING) != 0) { 237 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 238 return EFI_ABORTED; 239 } 240 } else { 241 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified"); 242 return Status; 243 } 244 // 245 // Read the read enabled capability attribute 246 // 247 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value); 248 249 if (Status == EFI_SUCCESS) { 250 // 251 // Update the read disabled flag 252 // 253 if (strcmp (Value, TRUE_STRING) == 0) { 254 FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP; 255 } else if (strcmp (Value, FALSE_STRING) != 0) { 256 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 257 return EFI_ABORTED; 258 } 259 } else { 260 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified"); 261 return Status; 262 } 263 // 264 // Read the read status attribute 265 // 266 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value); 267 268 if (Status == EFI_SUCCESS) { 269 // 270 // Update the read disabled flag 271 // 272 if (strcmp (Value, TRUE_STRING) == 0) { 273 FvInfo->FvAttributes |= EFI_FVB_READ_STATUS; 274 } else if (strcmp (Value, FALSE_STRING) != 0) { 275 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 276 return EFI_ABORTED; 277 } 278 } else { 279 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified"); 280 return Status; 281 } 282 // 283 // Read the write disabled capability attribute 284 // 285 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value); 286 287 if (Status == EFI_SUCCESS) { 288 // 289 // Update the write disabled flag 290 // 291 if (strcmp (Value, TRUE_STRING) == 0) { 292 FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP; 293 } else if (strcmp (Value, FALSE_STRING) != 0) { 294 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 295 return EFI_ABORTED; 296 } 297 } else { 298 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified"); 299 return Status; 300 } 301 // 302 // Read the write enabled capability attribute 303 // 304 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value); 305 306 if (Status == EFI_SUCCESS) { 307 // 308 // Update the write disabled flag 309 // 310 if (strcmp (Value, TRUE_STRING) == 0) { 311 FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP; 312 } else if (strcmp (Value, FALSE_STRING) != 0) { 313 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 314 return EFI_ABORTED; 315 } 316 } else { 317 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified"); 318 return Status; 319 } 320 // 321 // Read the write status attribute 322 // 323 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value); 324 325 if (Status == EFI_SUCCESS) { 326 // 327 // Update the write disabled flag 328 // 329 if (strcmp (Value, TRUE_STRING) == 0) { 330 FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS; 331 } else if (strcmp (Value, FALSE_STRING) != 0) { 332 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 333 return EFI_ABORTED; 334 } 335 } else { 336 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified"); 337 return Status; 338 } 339 // 340 // Read the lock capability attribute 341 // 342 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value); 343 344 if (Status == EFI_SUCCESS) { 345 // 346 // Update the attribute flag 347 // 348 if (strcmp (Value, TRUE_STRING) == 0) { 349 FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP; 350 } else if (strcmp (Value, FALSE_STRING) != 0) { 351 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 352 return EFI_ABORTED; 353 } 354 } else { 355 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified"); 356 return Status; 357 } 358 // 359 // Read the lock status attribute 360 // 361 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value); 362 363 if (Status == EFI_SUCCESS) { 364 // 365 // Update the attribute flag 366 // 367 if (strcmp (Value, TRUE_STRING) == 0) { 368 FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS; 369 } else if (strcmp (Value, FALSE_STRING) != 0) { 370 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 371 return EFI_ABORTED; 372 } 373 } else { 374 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified"); 375 return Status; 376 } 377 // 378 // Read the sticky write attribute 379 // 380 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value); 381 382 if (Status == EFI_SUCCESS) { 383 // 384 // Update the attribute flag 385 // 386 if (strcmp (Value, TRUE_STRING) == 0) { 387 FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE; 388 } else if (strcmp (Value, FALSE_STRING) != 0) { 389 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 390 return EFI_ABORTED; 391 } 392 } else { 393 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified"); 394 return Status; 395 } 396 // 397 // Read the memory mapped attribute 398 // 399 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value); 400 401 if (Status == EFI_SUCCESS) { 402 // 403 // Update the attribute flag 404 // 405 if (strcmp (Value, TRUE_STRING) == 0) { 406 FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED; 407 } else if (strcmp (Value, FALSE_STRING) != 0) { 408 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 409 return EFI_ABORTED; 410 } 411 } else { 412 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified"); 413 return Status; 414 } 415 // 416 // Read the erase polarity attribute 417 // 418 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value); 419 420 if (Status == EFI_SUCCESS) { 421 // 422 // Update the attribute flag 423 // 424 if (strcmp (Value, ONE_STRING) == 0) { 425 FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY; 426 } else if (strcmp (Value, ZERO_STRING) != 0) { 427 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 428 return EFI_ABORTED; 429 } 430 } else { 431 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified"); 432 return Status; 433 } 434 435 #if (PI_SPECIFICATION_VERSION >= 0x00010000) 436 // 437 // Read the read lock capability attribute 438 // 439 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value); 440 441 if (Status == EFI_SUCCESS) { 442 // 443 // Update attribute 444 // 445 if (strcmp (Value, TRUE_STRING) == 0) { 446 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP; 447 } else if (strcmp (Value, FALSE_STRING) != 0) { 448 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 449 return EFI_ABORTED; 450 } 451 } else { 452 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified"); 453 return Status; 454 } 455 456 // 457 // Read the read lock status attribute 458 // 459 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value); 460 461 if (Status == EFI_SUCCESS) { 462 // 463 // Update attribute 464 // 465 if (strcmp (Value, TRUE_STRING) == 0) { 466 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS; 467 } else if (strcmp (Value, FALSE_STRING) != 0) { 468 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 469 return EFI_ABORTED; 470 } 471 } else { 472 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified"); 473 return Status; 474 } 475 476 // 477 // Read the write lock capability attribute 478 // 479 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value); 480 481 if (Status == EFI_SUCCESS) { 482 // 483 // Update attribute 484 // 485 if (strcmp (Value, TRUE_STRING) == 0) { 486 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP; 487 } else if (strcmp (Value, FALSE_STRING) != 0) { 488 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 489 return EFI_ABORTED; 490 } 491 } else { 492 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified"); 493 return Status; 494 } 495 496 // 497 // Read the write lock status attribute 498 // 499 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value); 500 501 if (Status == EFI_SUCCESS) { 502 // 503 // Update attribute 504 // 505 if (strcmp (Value, TRUE_STRING) == 0) { 506 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS; 507 } else if (strcmp (Value, FALSE_STRING) != 0) { 508 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 509 return EFI_ABORTED; 510 } 511 } else { 512 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified"); 513 return Status; 514 } 515 #endif 516 517 #if (PI_SPECIFICATION_VERSION < 0x00010000) 518 // 519 // Read the alignment capabilities attribute 520 // 521 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value); 522 523 if (Status == EFI_SUCCESS) { 524 // 525 // Update attribute 526 // 527 if (strcmp (Value, TRUE_STRING) == 0) { 528 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP; 529 } else if (strcmp (Value, FALSE_STRING) != 0) { 530 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 531 return EFI_ABORTED; 532 } 533 } else { 534 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified"); 535 return Status; 536 } 537 538 // 539 // Read the word alignment capability attribute 540 // 541 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value); 542 543 if (Status == EFI_SUCCESS) { 544 // 545 // Update attribute 546 // 547 if (strcmp (Value, TRUE_STRING) == 0) { 548 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2; 549 } else if (strcmp (Value, FALSE_STRING) != 0) { 550 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 551 return EFI_ABORTED; 552 } 553 } else { 554 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified"); 555 return Status; 556 } 557 558 559 // 560 // Read the dword alignment capability attribute 561 // 562 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value); 563 564 if (Status == EFI_SUCCESS) { 565 // 566 // Update attribute 567 // 568 if (strcmp (Value, TRUE_STRING) == 0) { 569 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4; 570 } else if (strcmp (Value, FALSE_STRING) != 0) { 571 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 572 return EFI_ABORTED; 573 } 574 } else { 575 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified"); 576 return Status; 577 } 578 // 579 // Read the word alignment capability attribute 580 // 581 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value); 582 583 if (Status == EFI_SUCCESS) { 584 // 585 // Update attribute 586 // 587 if (strcmp (Value, TRUE_STRING) == 0) { 588 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8; 589 } else if (strcmp (Value, FALSE_STRING) != 0) { 590 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 591 return EFI_ABORTED; 592 } 593 } else { 594 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified"); 595 return Status; 596 } 597 // 598 // Read the qword alignment capability attribute 599 // 600 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value); 601 602 if (Status == EFI_SUCCESS) { 603 // 604 // Update attribute 605 // 606 if (strcmp (Value, TRUE_STRING) == 0) { 607 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16; 608 } else if (strcmp (Value, FALSE_STRING) != 0) { 609 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 610 return EFI_ABORTED; 611 } 612 } else { 613 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified"); 614 return Status; 615 } 616 // 617 // Read the 32 byte alignment capability attribute 618 // 619 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value); 620 621 if (Status == EFI_SUCCESS) { 622 // 623 // Update attribute 624 // 625 if (strcmp (Value, TRUE_STRING) == 0) { 626 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32; 627 } else if (strcmp (Value, FALSE_STRING) != 0) { 628 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 629 return EFI_ABORTED; 630 } 631 } else { 632 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified"); 633 return Status; 634 } 635 // 636 // Read the 64 byte alignment capability attribute 637 // 638 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value); 639 640 if (Status == EFI_SUCCESS) { 641 // 642 // Update attribute 643 // 644 if (strcmp (Value, TRUE_STRING) == 0) { 645 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64; 646 } else if (strcmp (Value, FALSE_STRING) != 0) { 647 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 648 return EFI_ABORTED; 649 } 650 } else { 651 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified"); 652 return Status; 653 } 654 // 655 // Read the 128 byte alignment capability attribute 656 // 657 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value); 658 659 if (Status == EFI_SUCCESS) { 660 // 661 // Update attribute 662 // 663 if (strcmp (Value, TRUE_STRING) == 0) { 664 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128; 665 } else if (strcmp (Value, FALSE_STRING) != 0) { 666 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 667 return EFI_ABORTED; 668 } 669 } else { 670 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified"); 671 return Status; 672 } 673 // 674 // Read the 256 byte alignment capability attribute 675 // 676 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value); 677 678 if (Status == EFI_SUCCESS) { 679 // 680 // Update attribute 681 // 682 if (strcmp (Value, TRUE_STRING) == 0) { 683 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256; 684 } else if (strcmp (Value, FALSE_STRING) != 0) { 685 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 686 return EFI_ABORTED; 687 } 688 } else { 689 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified"); 690 return Status; 691 } 692 // 693 // Read the 512 byte alignment capability attribute 694 // 695 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value); 696 697 if (Status == EFI_SUCCESS) { 698 // 699 // Update attribute 700 // 701 if (strcmp (Value, TRUE_STRING) == 0) { 702 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512; 703 } else if (strcmp (Value, FALSE_STRING) != 0) { 704 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 705 return EFI_ABORTED; 706 } 707 } else { 708 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified"); 709 return Status; 710 } 711 // 712 // Read the 1K byte alignment capability attribute 713 // 714 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value); 715 716 if (Status == EFI_SUCCESS) { 717 // 718 // Update attribute 719 // 720 if (strcmp (Value, TRUE_STRING) == 0) { 721 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K; 722 } else if (strcmp (Value, FALSE_STRING) != 0) { 723 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 724 return EFI_ABORTED; 725 } 726 } else { 727 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified"); 728 return Status; 729 } 730 // 731 // Read the 2K byte alignment capability attribute 732 // 733 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value); 734 735 if (Status == EFI_SUCCESS) { 736 // 737 // Update attribute 738 // 739 if (strcmp (Value, TRUE_STRING) == 0) { 740 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K; 741 } else if (strcmp (Value, FALSE_STRING) != 0) { 742 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 743 return EFI_ABORTED; 744 } 745 } else { 746 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified"); 747 return Status; 748 } 749 // 750 // Read the 4K byte alignment capability attribute 751 // 752 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value); 753 754 if (Status == EFI_SUCCESS) { 755 // 756 // Update attribute 757 // 758 if (strcmp (Value, TRUE_STRING) == 0) { 759 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K; 760 } else if (strcmp (Value, FALSE_STRING) != 0) { 761 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 762 return EFI_ABORTED; 763 } 764 } else { 765 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified"); 766 return Status; 767 } 768 // 769 // Read the 8K byte alignment capability attribute 770 // 771 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value); 772 773 if (Status == EFI_SUCCESS) { 774 // 775 // Update attribute 776 // 777 if (strcmp (Value, TRUE_STRING) == 0) { 778 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K; 779 } else if (strcmp (Value, FALSE_STRING) != 0) { 780 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 781 return EFI_ABORTED; 782 } 783 } else { 784 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified"); 785 return Status; 786 } 787 // 788 // Read the 16K byte alignment capability attribute 789 // 790 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value); 791 792 if (Status == EFI_SUCCESS) { 793 // 794 // Update attribute 795 // 796 if (strcmp (Value, TRUE_STRING) == 0) { 797 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K; 798 } else if (strcmp (Value, FALSE_STRING) != 0) { 799 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 800 return EFI_ABORTED; 801 } 802 } else { 803 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified"); 804 return Status; 805 } 806 // 807 // Read the 32K byte alignment capability attribute 808 // 809 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value); 810 811 if (Status == EFI_SUCCESS) { 812 // 813 // Update attribute 814 // 815 if (strcmp (Value, TRUE_STRING) == 0) { 816 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K; 817 } else if (strcmp (Value, FALSE_STRING) != 0) { 818 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 819 return EFI_ABORTED; 820 } 821 } else { 822 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified"); 823 return Status; 824 } 825 // 826 // Read the 64K byte alignment capability attribute 827 // 828 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value); 829 830 if (Status == EFI_SUCCESS) { 831 // 832 // Update attribute 833 // 834 if (strcmp (Value, TRUE_STRING) == 0) { 835 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K; 836 } else if (strcmp (Value, FALSE_STRING) != 0) { 837 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); 838 return EFI_ABORTED; 839 } 840 } else { 841 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified"); 842 return Status; 843 } 844 845 if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) && 846 ( 847 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) || 848 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) || 849 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) || 850 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) || 851 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) || 852 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) || 853 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) || 854 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) || 855 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) || 856 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) || 857 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) || 858 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) || 859 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) || 860 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) || 861 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) || 862 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K) 863 ) 864 ){ 865 Error ( 866 NULL, 867 0, 868 0, 869 "illegal combination of alignment attributes", 870 "if %s is not %s, no individual alignments can be %s", 871 EFI_FVB_ALIGNMENT_CAP_STRING, 872 TRUE_STRING, 873 TRUE_STRING 874 ); 875 return EFI_ABORTED; 876 } 877 #else 878 // 879 // Read the PI1.0 FVB2 Alignment Capabilities Attribute 880 // 881 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value); 882 883 if (Status == EFI_SUCCESS) { 884 // 885 // Update attribute 886 // 887 if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) { 888 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1; 889 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) { 890 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2; 891 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) { 892 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4; 893 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) { 894 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8; 895 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) { 896 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16; 897 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) { 898 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32; 899 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) { 900 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64; 901 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) { 902 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128; 903 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) { 904 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256; 905 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) { 906 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512; 907 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) { 908 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K; 909 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) { 910 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K; 911 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) { 912 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K; 913 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) { 914 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K; 915 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) { 916 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K; 917 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) { 918 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K; 919 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) { 920 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K; 921 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) { 922 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K; 923 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) { 924 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K; 925 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) { 926 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512K; 927 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) { 928 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M; 929 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) { 930 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M; 931 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) { 932 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M; 933 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) { 934 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M; 935 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) { 936 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M; 937 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) { 938 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M; 939 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) { 940 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M; 941 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) { 942 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M; 943 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) { 944 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M; 945 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) { 946 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M; 947 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) { 948 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G; 949 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) { 950 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G; 951 } else { 952 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!"); 953 return EFI_ABORTED; 954 } 955 } else { 956 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified"); 957 return Status; 958 } 959 960 #endif 961 // 962 // Read block maps 963 // 964 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { 965 // 966 // Read the number of blocks 967 // 968 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); 969 970 if (Status == EFI_SUCCESS) { 971 if (strcmp (Value, AUTO_STRING) == 0) { 972 Value64 = (UINT64) -1; 973 } else { 974 // 975 // Update the number of blocks 976 // 977 Status = AsciiStringToUint64 (Value, FALSE, &Value64); 978 if (EFI_ERROR (Status)) { 979 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING); 980 return EFI_ABORTED; 981 } 982 } 983 984 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; 985 } else { 986 // 987 // If there is no number of blocks, but there is a size, then we have a mismatched pair 988 // and should return an error. 989 // 990 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); 991 if (!EFI_ERROR (Status)) { 992 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); 993 return EFI_ABORTED; 994 } else { 995 // 996 // We are done 997 // 998 break; 999 } 1000 } 1001 // 1002 // Read the size of blocks 1003 // 1004 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); 1005 1006 if (Status == EFI_SUCCESS) { 1007 // 1008 // Update the number of blocks 1009 // 1010 Status = AsciiStringToUint64 (Value, FALSE, &Value64); 1011 if (EFI_ERROR (Status)) { 1012 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING); 1013 return EFI_ABORTED; 1014 } 1015 1016 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64; 1017 } else { 1018 // 1019 // There is a number of blocks, but there is no size, so we have a mismatched pair 1020 // and should return an error. 1021 // 1022 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); 1023 return EFI_ABORTED; 1024 } 1025 } 1026 // 1027 // Read files 1028 // 1029 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { 1030 // 1031 // Read the number of blocks 1032 // 1033 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); 1034 1035 if (Status == EFI_SUCCESS) { 1036 // 1037 // Add the file 1038 // 1039 strcpy (FvInfo->FvFiles[Index], Value); 1040 } else { 1041 break; 1042 } 1043 } 1044 1045 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) { 1046 Index = 0; 1047 while (TRUE) { 1048 Status = FindTokenInstanceInSection ( 1049 InfFile, 1050 COMPONENT_SECTION_STRING, 1051 Index, 1052 FvInfo->FvComponents[Index].ComponentName, 1053 Value 1054 ); 1055 if (EFI_ERROR (Status)) { 1056 break; 1057 } 1058 Status = AsciiStringToUint64 (Value, FALSE, &Value64); 1059 if (EFI_ERROR (Status)) { 1060 Error (NULL, 0, 0, Value, "not a valid integer"); 1061 return EFI_ABORTED; 1062 } 1063 1064 FvInfo->FvComponents[Index].Size = (UINTN) Value64; 1065 Index++; 1066 } 1067 } 1068 // 1069 // Compute size for easy access later 1070 // 1071 FvInfo->Size = 0; 1072 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) { 1073 if ((FvInfo->Size == (UINTN) -1 && Index > 0) || 1074 (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1 && Index > 0) 1075 ) { 1076 // 1077 // Error 1. more pairs after AUTO 1078 // Error 2. AUTO appear in non-first position 1079 // 1080 Error (NULL, 0, 0, NULL, "cannot have more than one pair of %s and %s if %s is set to %s", 1081 EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING, 1082 EFI_NUM_BLOCKS_STRING, AUTO_STRING 1083 ); 1084 return EFI_ABORTED; 1085 } 1086 1087 if (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1) { 1088 FvInfo->Size = (UINTN) -1; 1089 } else { 1090 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength; 1091 } 1092 } 1093 1094 if (FvInfo->Size == (UINTN) -1 && FvInfo->FvFiles[0][0] == 0) { 1095 // 1096 // Non FFS FV cannot set block number to AUTO 1097 // 1098 Error (NULL, 0, 0, "non-FFS FV", "cannot set %s to %s", EFI_NUM_BLOCKS_STRING, AUTO_STRING); 1099 return EFI_ABORTED; 1100 } 1101 1102 return EFI_SUCCESS; 1103 } 1104 1105 VOID 1106 UpdateFfsFileState ( 1107 IN EFI_FFS_FILE_HEADER *FfsFile, 1108 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader 1109 ) 1110 /*++ 1111 1112 Routine Description: 1113 1114 This function changes the FFS file attributes based on the erase polarity 1115 of the FV. 1116 1117 Arguments: 1118 1119 FfsFile File header. 1120 FvHeader FV header. 1121 1122 Returns: 1123 1124 None 1125 1126 --*/ 1127 { 1128 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { 1129 FfsFile->State = (UINT8)~(FfsFile->State); 1130 } 1131 } 1132 1133 EFI_STATUS 1134 ReadFfsAlignment ( 1135 IN EFI_FFS_FILE_HEADER *FfsFile, 1136 IN OUT UINT32 *Alignment 1137 ) 1138 /*++ 1139 1140 Routine Description: 1141 1142 This function determines the alignment of the FFS input file from the file 1143 attributes. 1144 1145 Arguments: 1146 1147 FfsFile FFS file to parse 1148 Alignment The minimum required alignment of the FFS file, in bytes 1149 1150 Returns: 1151 1152 EFI_SUCCESS The function completed successfully. 1153 EFI_INVALID_PARAMETER One of the input parameters was invalid. 1154 EFI_ABORTED An error occurred. 1155 1156 --*/ 1157 { 1158 // 1159 // Verify input parameters. 1160 // 1161 if (FfsFile == NULL || Alignment == NULL) { 1162 return EFI_INVALID_PARAMETER; 1163 } 1164 1165 switch ((FfsFile->Attributes >> 3) & 0x07) { 1166 1167 case 0: 1168 // 1169 // 1 byte alignment 1170 // 1171 *Alignment = (1 << 0); 1172 break; 1173 1174 case 1: 1175 // 1176 // 16 byte alignment 1177 // 1178 *Alignment = (1 << 4); 1179 break; 1180 1181 case 2: 1182 // 1183 // 128 byte alignment 1184 // 1185 *Alignment = (1 << 7); 1186 break; 1187 1188 case 3: 1189 // 1190 // 512 byte alignment 1191 // 1192 *Alignment = (1 << 9); 1193 break; 1194 1195 case 4: 1196 // 1197 // 1K byte alignment 1198 // 1199 *Alignment = (1 << 10); 1200 break; 1201 1202 case 5: 1203 // 1204 // 4K byte alignment 1205 // 1206 *Alignment = (1 << 12); 1207 break; 1208 1209 case 6: 1210 // 1211 // 32K byte alignment 1212 // 1213 *Alignment = (1 << 15); 1214 break; 1215 1216 case 7: 1217 // 1218 // 64K byte alignment 1219 // 1220 *Alignment = (1 << 16); 1221 break; 1222 1223 default: 1224 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL); 1225 return EFI_ABORTED; 1226 } 1227 1228 return EFI_SUCCESS; 1229 } 1230 1231 EFI_STATUS 1232 AddPadFile ( 1233 IN OUT MEMORY_FILE *FvImage, 1234 IN UINT32 DataAlignment 1235 ) 1236 /*++ 1237 1238 Routine Description: 1239 1240 This function adds a pad file to the FV image if it required to align the 1241 data of the next file. 1242 1243 Arguments: 1244 1245 FvImage The memory image of the FV to add it to. The current offset 1246 must be valid. 1247 DataAlignment The data alignment of the next FFS file. 1248 1249 Returns: 1250 1251 EFI_SUCCESS The function completed successfully. 1252 EFI_INVALID_PARAMETER One of the input parameters was invalid. 1253 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete 1254 the pad file add. 1255 1256 --*/ 1257 { 1258 EFI_FFS_FILE_HEADER *PadFile; 1259 UUID PadFileGuid; 1260 UINTN PadFileSize; 1261 1262 // 1263 // Verify input parameters. 1264 // 1265 if (FvImage == NULL) { 1266 return EFI_INVALID_PARAMETER; 1267 } 1268 // 1269 // Basic assumption is we start from an 8 byte aligned address 1270 // and our file header is a multiple of 8 bytes 1271 // 1272 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0); 1273 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0); 1274 1275 // 1276 // Check if a pad file is necessary 1277 // 1278 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) { 1279 return EFI_SUCCESS; 1280 } 1281 // 1282 // Write pad file header 1283 // 1284 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; 1285 1286 // 1287 // Verify that we have enough space for the file header 1288 // 1289 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { 1290 return EFI_OUT_OF_RESOURCES; 1291 } 1292 1293 UuidCreate (&PadFileGuid); 1294 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); 1295 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID)); 1296 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; 1297 PadFile->Attributes = 0; 1298 1299 // 1300 // Calculate the pad file size 1301 // 1302 // 1303 // This is the earliest possible valid offset (current plus pad file header 1304 // plus the next file header) 1305 // 1306 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2); 1307 1308 // 1309 // Add whatever it takes to get to the next aligned address 1310 // 1311 while ((PadFileSize % DataAlignment) != 0) { 1312 PadFileSize++; 1313 } 1314 // 1315 // Subtract the next file header size 1316 // 1317 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER); 1318 1319 // 1320 // Subtract the starting offset to get size 1321 // 1322 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage; 1323 1324 // 1325 // Write pad file size (calculated size minus next file header size) 1326 // 1327 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF); 1328 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF); 1329 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF); 1330 1331 // 1332 // Fill in checksums and state, they must be 0 for checksumming. 1333 // 1334 PadFile->IntegrityCheck.Checksum.Header = 0; 1335 PadFile->IntegrityCheck.Checksum.File = 0; 1336 PadFile->State = 0; 1337 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); 1338 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { 1339 #if (PI_SPECIFICATION_VERSION < 0x00010000) 1340 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize); 1341 #else 1342 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN)PadFile + sizeof (EFI_FFS_FILE_HEADER)), PadFileSize - sizeof (EFI_FFS_FILE_HEADER)); 1343 #endif 1344 } else { 1345 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; 1346 } 1347 1348 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; 1349 UpdateFfsFileState ( 1350 (EFI_FFS_FILE_HEADER *) PadFile, 1351 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage 1352 ); 1353 1354 // 1355 // Verify that we have enough space (including the padding 1356 // 1357 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { 1358 return EFI_OUT_OF_RESOURCES; 1359 } 1360 // 1361 // Update the current FV pointer 1362 // 1363 FvImage->CurrentFilePointer += PadFileSize; 1364 1365 return EFI_SUCCESS; 1366 } 1367 1368 BOOLEAN 1369 IsVtfFile ( 1370 IN EFI_FFS_FILE_HEADER *FileBuffer 1371 ) 1372 /*++ 1373 1374 Routine Description: 1375 1376 This function checks the header to validate if it is a VTF file 1377 1378 Arguments: 1379 1380 FileBuffer Buffer in which content of a file has been read. 1381 1382 Returns: 1383 1384 TRUE If this is a VTF file 1385 FALSE If this is not a VTF file 1386 1387 --*/ 1388 { 1389 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; 1390 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) { 1391 return TRUE; 1392 } else { 1393 return FALSE; 1394 } 1395 } 1396 1397 EFI_STATUS 1398 FfsRebaseImageRead ( 1399 IN VOID *FileHandle, 1400 IN UINTN FileOffset, 1401 IN OUT UINT32 *ReadSize, 1402 OUT VOID *Buffer 1403 ) 1404 /*++ 1405 1406 Routine Description: 1407 1408 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file 1409 1410 Arguments: 1411 1412 FileHandle - The handle to the PE/COFF file 1413 1414 FileOffset - The offset, in bytes, into the file to read 1415 1416 ReadSize - The number of bytes to read from the file starting at FileOffset 1417 1418 Buffer - A pointer to the buffer to read the data into. 1419 1420 Returns: 1421 1422 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset 1423 1424 --*/ 1425 { 1426 CHAR8 *Destination8; 1427 CHAR8 *Source8; 1428 UINT32 Length; 1429 1430 Destination8 = Buffer; 1431 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); 1432 Length = *ReadSize; 1433 while (Length--) { 1434 *(Destination8++) = *(Source8++); 1435 } 1436 1437 return EFI_SUCCESS; 1438 } 1439 1440 EFI_STATUS 1441 RebaseFfsFile ( 1442 IN OUT EFI_FFS_FILE_HEADER *FfsFile, 1443 IN EFI_PHYSICAL_ADDRESS BaseAddress 1444 ) 1445 /*++ 1446 1447 Routine Description: 1448 1449 This function determines if a file is XIP and should be rebased. It will 1450 rebase any PE32 sections found in the file using the base address. 1451 1452 Arguments: 1453 1454 FfsFile A pointer to Ffs file image. 1455 BaseAddress The base address to use for rebasing the file image. 1456 1457 Returns: 1458 1459 EFI_SUCCESS The image was properly rebased. 1460 EFI_INVALID_PARAMETER An input parameter is invalid. 1461 EFI_ABORTED An error occurred while rebasing the input file image. 1462 EFI_OUT_OF_RESOURCES Could not allocate a required resource. 1463 1464 --*/ 1465 { 1466 EFI_STATUS Status; 1467 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 1468 UINTN MemoryImagePointer; 1469 UINTN MemoryImagePointerAligned; 1470 1471 EFI_PHYSICAL_ADDRESS ImageAddress; 1472 UINT64 ImageSize; 1473 EFI_PHYSICAL_ADDRESS EntryPoint; 1474 1475 UINT32 Pe32FileSize; 1476 UINT32 NewPe32BaseAddress; 1477 1478 UINTN Index; 1479 EFI_FILE_SECTION_POINTER CurrentPe32Section; 1480 UINT8 FileGuidString[80]; 1481 1482 // 1483 // Verify input parameters 1484 // 1485 if (FfsFile == NULL) { 1486 return EFI_INVALID_PARAMETER; 1487 } 1488 // 1489 // Convert the GUID to a string so we can at least report which file 1490 // if we find an error. 1491 // 1492 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE); 1493 1494 // 1495 // Do some nominal checks on the file, then check for XIP. 1496 // 1497 Status = VerifyFfsFile (FfsFile); 1498 if (EFI_ERROR (Status)) { 1499 Error (NULL, 0, 0, "invalid FFS file", FileGuidString); 1500 return EFI_INVALID_PARAMETER; 1501 } 1502 1503 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && 1504 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && 1505 FfsFile->Type != EFI_FV_FILETYPE_PEIM 1506 ) { 1507 // 1508 // File is not XIP, so don't rebase 1509 // 1510 return EFI_SUCCESS; 1511 } 1512 // 1513 // Rebase each PE32 section 1514 // 1515 for (Index = 1;; Index++) { 1516 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); 1517 if (EFI_ERROR (Status)) { 1518 break; 1519 } 1520 // 1521 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section 1522 // 1523 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile); 1524 1525 // 1526 // Initialize context 1527 // 1528 memset (&ImageContext, 0, sizeof (ImageContext)); 1529 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION)); 1530 ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; 1531 1532 Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext); 1533 1534 if (EFI_ERROR (Status)) { 1535 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString); 1536 return Status; 1537 } 1538 // 1539 // Allocate a buffer for the image to be loaded into. 1540 // 1541 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size); 1542 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000)); 1543 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12); 1544 if (MemoryImagePointerAligned == 0) { 1545 Error (NULL, 0, 0, "memory allocation failure", NULL); 1546 return EFI_OUT_OF_RESOURCES; 1547 } 1548 1549 // 1550 // bugbug 1551 // 1552 ImageContext.ImageAddress = MemoryImagePointerAligned; 1553 Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext); 1554 if (EFI_ERROR (Status)) { 1555 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString); 1556 free ((VOID *) MemoryImagePointer); 1557 return Status; 1558 } 1559 1560 Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext); 1561 if (EFI_ERROR (Status)) { 1562 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString); 1563 free ((VOID *) MemoryImagePointer); 1564 return Status; 1565 } 1566 1567 ImageAddress = ImageContext.ImageAddress; 1568 ImageSize = ImageContext.ImageSize; 1569 EntryPoint = ImageContext.EntryPoint; 1570 1571 if (ImageSize > Pe32FileSize) { 1572 Error ( 1573 NULL, 1574 0, 1575 0, 1576 "rebased PE32 is larger than original PE32 image", 1577 "0x%X > 0x%X on file %s", 1578 ImageSize, 1579 Pe32FileSize, 1580 FileGuidString 1581 ); 1582 free ((VOID *) MemoryImagePointer); 1583 return EFI_ABORTED; 1584 } 1585 1586 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize); 1587 1588 free ((VOID *) MemoryImagePointer); 1589 } 1590 // 1591 // the above for loop will always exit with EFI_NOT_FOUND if it completes 1592 // normally. If Index == 1 at exit, then no PE32 sections were found. If it 1593 // exits with any other error code, then something broke... 1594 // 1595 if (Status != EFI_NOT_FOUND) { 1596 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString); 1597 return Status; 1598 } 1599 1600 return EFI_SUCCESS; 1601 } 1602 1603 EFI_STATUS 1604 AddSymFile ( 1605 IN UINT64 BaseAddress, 1606 IN EFI_FFS_FILE_HEADER *FfsFile, 1607 IN OUT MEMORY_FILE *SymImage, 1608 IN CHAR8 *SourceFileName 1609 ) 1610 /*++ 1611 1612 Routine Description: 1613 1614 This function adds the SYM tokens in the source file to the destination file. 1615 The SYM tokens are updated to reflect the base address. 1616 1617 Arguments: 1618 1619 BaseAddress The base address for the new SYM tokens. 1620 FfsFile Pointer to the beginning of the FFS file in question. 1621 SymImage The memory file to update with symbol information. 1622 SourceFileName The source file. 1623 1624 Returns: 1625 1626 EFI_SUCCESS The function completed successfully. 1627 EFI_INVALID_PARAMETER One of the input parameters was invalid. 1628 EFI_ABORTED An error occurred. 1629 1630 --*/ 1631 { 1632 FILE *SourceFile; 1633 1634 CHAR8 Buffer[_MAX_PATH]; 1635 CHAR8 Type[_MAX_PATH]; 1636 CHAR8 Address[_MAX_PATH]; 1637 CHAR8 Section[_MAX_PATH]; 1638 CHAR8 Token[_MAX_PATH]; 1639 CHAR8 SymFileName[_MAX_PATH]; 1640 CHAR8 CodeModuleName[_MAX_PATH]; 1641 CHAR8 *Ptr; 1642 1643 UINT64 TokenAddress; 1644 1645 EFI_STATUS Status; 1646 EFI_FILE_SECTION_POINTER Pe32Section; 1647 UINT32 EntryPoint; 1648 UINT32 BaseOfCode; 1649 UINT16 MachineType; 1650 1651 // 1652 // Verify input parameters. 1653 // 1654 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) { 1655 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL); 1656 return EFI_INVALID_PARAMETER; 1657 } 1658 // 1659 // Check if we want to add this file 1660 // 1661 // 1662 // Get the file name 1663 // 1664 strcpy (Buffer, SourceFileName); 1665 1666 // 1667 // Copy the file name for the path of the sym file and truncate the name portion. 1668 // 1669 strcpy (SymFileName, Buffer); 1670 Ptr = strrchr (SymFileName, '\\'); 1671 assert (Ptr); 1672 Ptr[0] = 0; 1673 1674 // 1675 // Find the file extension and make it lower case 1676 // 1677 Ptr = strrchr (SymFileName, '.'); 1678 if (Ptr != NULL) { 1679 _strlwr (Ptr); 1680 } 1681 // 1682 // Check if it is PEI file 1683 // 1684 if (strstr (Buffer, ".pei") != NULL) { 1685 // 1686 // Find the human readable portion 1687 // 1688 if (!strtok (Buffer, "-") || 1689 !strtok (NULL, "-") || 1690 !strtok (NULL, "-") || 1691 !strtok (NULL, "-") || 1692 !strtok (NULL, "-") || 1693 !strcpy (Buffer, strtok (NULL, ".")) 1694 ) { 1695 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL); 1696 return EFI_ABORTED; 1697 } 1698 // 1699 // Save code module name 1700 // 1701 strcpy (CodeModuleName, Buffer); 1702 1703 // 1704 // Add the symbol file name and extension to the file path. 1705 // 1706 strcat (Buffer, ".sym"); 1707 strcat (SymFileName, "\\"); 1708 strcat (SymFileName, Buffer); 1709 } else { 1710 // 1711 // Only handle PEIM files. 1712 // 1713 return EFI_SUCCESS; 1714 } 1715 // 1716 // Find PE32 section 1717 // 1718 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section); 1719 1720 // 1721 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address 1722 // 1723 if (Status == EFI_NOT_FOUND) { 1724 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section); 1725 } 1726 1727 if (Status == EFI_SUCCESS) { 1728 Status = GetPe32Info ( 1729 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), 1730 &EntryPoint, 1731 &BaseOfCode, 1732 &MachineType 1733 ); 1734 } else { 1735 if (Status == EFI_NOT_FOUND) { 1736 BaseOfCode = 0x60; 1737 Status = EFI_SUCCESS; 1738 } else { 1739 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL); 1740 return Status; 1741 } 1742 } 1743 1744 if (EFI_ERROR (Status)) { 1745 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL); 1746 return Status; 1747 } 1748 1749 // 1750 // Open the source file 1751 // 1752 SourceFile = fopen (SymFileName, "r"); 1753 if (SourceFile == NULL) { 1754 // 1755 // SYM files are not required. 1756 // 1757 return EFI_SUCCESS; 1758 } 1759 // 1760 // Read the first line 1761 // 1762 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) { 1763 Buffer[0] = 0; 1764 } 1765 // 1766 // Make sure it matches the expected sym format 1767 // 1768 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) { 1769 fclose (SourceFile); 1770 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL); 1771 return EFI_ABORTED; 1772 } 1773 // 1774 // Read in the file 1775 // 1776 while (feof (SourceFile) == 0) { 1777 // 1778 // Read a line 1779 // 1780 if (fscanf ( 1781 SourceFile, 1782 "%s | %s | %s | %s\n", 1783 Type, 1784 Address, 1785 Section, 1786 Token 1787 ) == 4) { 1788 // 1789 // If the token starts with "??" ignore it 1790 // 1791 if (Token[0] == '?' && Token[1] == '?') { 1792 continue; 1793 } 1794 // 1795 // Get the token address 1796 // 1797 AsciiStringToUint64 (Address, TRUE, &TokenAddress); 1798 1799 // 1800 // Add the base address 1801 // 1802 TokenAddress += BaseAddress; 1803 1804 // 1805 // If PE32 or TE section then find the start of code. For PIC it is hardcoded. 1806 // 1807 if (Pe32Section.Pe32Section) { 1808 // 1809 // Add the offset of the PE32 section 1810 // 1811 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile; 1812 1813 // 1814 // Add the size of the PE32 section header 1815 // 1816 TokenAddress += sizeof (EFI_PE32_SECTION); 1817 } else { 1818 // 1819 // BUGBUG: Don't know why this is 0x28 bytes. 1820 // 1821 TokenAddress += 0x28; 1822 } 1823 // 1824 // Add the beginning of the code 1825 // 1826 TokenAddress += BaseOfCode; 1827 1828 sprintf ( 1829 Buffer, 1830 "%s | %016I64X | %s | _%s%s\n", 1831 Type, 1832 TokenAddress, 1833 Section, 1834 CodeModuleName, 1835 Token 1836 ); 1837 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1); 1838 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1); 1839 } 1840 } 1841 1842 fclose (SourceFile); 1843 return EFI_SUCCESS; 1844 } 1845 1846 EFI_STATUS 1847 ReallocateFvImage ( 1848 IN OUT MEMORY_FILE *FvImage, 1849 IN OUT FV_INFO *FvInfo, 1850 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, 1851 IN OUT UINTN *FvImageCapacity 1852 ) 1853 /*++ 1854 Routine Description: 1855 Increase the size of FV image by 1 block. The routine may reallocate memory 1856 depending on the capacity of the FV image. 1857 1858 Arguments: 1859 FvImage The memory image of the FV to add it to. The current offset 1860 must be valid. 1861 FvInfo Pointer to information about the FV. 1862 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal 1863 to the end of the FvImage then no VTF previously found. 1864 FvImageCapacity Capacity of image buffer for FV. 1865 1866 Returns: 1867 EFI_SUCCESS The function completed successfully. 1868 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the reallocation. 1869 1870 --*/ 1871 { 1872 CHAR8 *FileImage; 1873 UINTN OldSize; 1874 UINTN IncreaseSize; 1875 EFI_FIRMWARE_VOLUME_HEADER *FvHeader; 1876 BOOLEAN AllocateNewMemory; 1877 EFI_FFS_FILE_HEADER *NewVtfFileImage; 1878 UINT32 VtfFileLength; 1879 UINT8 TempByte; 1880 1881 OldSize = (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage; 1882 IncreaseSize = FvInfo->FvBlocks[0].BlockLength; 1883 assert (OldSize == FvInfo->FvBlocks[0].NumBlocks * FvInfo->FvBlocks[0].BlockLength); 1884 1885 // 1886 // Assume we have enough capacity 1887 // 1888 AllocateNewMemory = FALSE; 1889 1890 1891 if (OldSize + IncreaseSize > *FvImageCapacity) { 1892 AllocateNewMemory = TRUE; 1893 // 1894 // Increase capacity by one unit 1895 // 1896 *FvImageCapacity = OldSize + FV_CAPACITY_INCREASE_UNIT; 1897 FileImage = malloc (*FvImageCapacity); 1898 1899 if (FileImage == NULL) { 1900 Error (NULL, 0, 0, "memory allocation failure", NULL); 1901 return EFI_OUT_OF_RESOURCES; 1902 } 1903 1904 // 1905 // Initialize the content per FV polarity 1906 // 1907 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) { 1908 memset (FileImage, -1, *FvImageCapacity); 1909 } else { 1910 memset (FileImage, 0, *FvImageCapacity); 1911 } 1912 1913 // 1914 // Copy the FV content before VTF 1915 // 1916 memcpy (FileImage, FvImage->FileImage, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage); 1917 } else { 1918 FileImage = FvImage->FileImage; 1919 } 1920 1921 // 1922 // Move VTF if it exists 1923 // 1924 NewVtfFileImage = (EFI_FFS_FILE_HEADER *) (FileImage + ((UINTN) *VtfFileImage - (UINTN) FvImage->FileImage) + IncreaseSize); 1925 if ((UINTN) *VtfFileImage != (UINTN) FvImage->Eof) { 1926 // 1927 // Exchange the VTF buffer from end to start for two purpose: 1928 // 1. Exchange: Preserve the default value per FV polarity 1929 // 2. End->Start: Avoid destroying the VTF data during exchanging 1930 // 1931 VtfFileLength = GetLength ((*VtfFileImage)->Size); 1932 while (VtfFileLength-- != 0) { 1933 TempByte = ((UINT8 *) VtfFileImage)[VtfFileLength]; 1934 ((UINT8 *) VtfFileImage)[VtfFileLength] = ((UINT8 *) NewVtfFileImage)[VtfFileLength]; 1935 ((UINT8 *) NewVtfFileImage)[VtfFileLength] = TempByte; 1936 } 1937 } 1938 1939 // 1940 // Update VTF Pointer 1941 // 1942 *VtfFileImage = NewVtfFileImage; 1943 1944 // 1945 // Update FvInfo 1946 // 1947 FvInfo->FvBlocks[0].NumBlocks ++; 1948 1949 // 1950 // Update FV Header 1951 // 1952 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FileImage; 1953 FvHeader->FvBlockMap[0].NumBlocks = FvInfo->FvBlocks[0].NumBlocks; 1954 FvHeader->FvLength = OldSize + IncreaseSize; 1955 FvHeader->Checksum = 0; 1956 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); 1957 1958 // 1959 // Update FvImage 1960 // 1961 if (AllocateNewMemory) { 1962 free (FvImage->FileImage); 1963 FvImage->CurrentFilePointer = FileImage + (FvImage->CurrentFilePointer - FvImage->FileImage); 1964 FvImage->FileImage = FileImage; 1965 } 1966 FvImage->Eof = FvImage->FileImage + OldSize + IncreaseSize; 1967 1968 InitializeFvLib (FvImage->FileImage, OldSize + IncreaseSize); 1969 return EFI_SUCCESS; 1970 } 1971 1972 EFI_STATUS 1973 AddFile ( 1974 IN OUT MEMORY_FILE *FvImage, 1975 IN FV_INFO *FvInfo, 1976 IN UINTN Index, 1977 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, 1978 IN OUT MEMORY_FILE *SymImage, 1979 IN OUT UINTN *FvImageCapacity 1980 ) 1981 /*++ 1982 1983 Routine Description: 1984 1985 This function adds a file to the FV image. The file will pad to the 1986 appropriate alignment if required. 1987 1988 Arguments: 1989 1990 FvImage The memory image of the FV to add it to. The current offset 1991 must be valid. 1992 FvInfo Pointer to information about the FV. 1993 Index The file in the FvInfo file list to add. 1994 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal 1995 to the end of the FvImage then no VTF previously found. 1996 SymImage The memory image of the Sym file to update if symbols are present. 1997 The current offset must be valid. 1998 FvImageCapacity Capacity of image buffer for FV. 1999 2000 Returns: 2001 2002 EFI_SUCCESS The function completed successfully. 2003 EFI_INVALID_PARAMETER One of the input parameters was invalid. 2004 EFI_ABORTED An error occurred. 2005 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. 2006 2007 --*/ 2008 { 2009 FILE *NewFile; 2010 UINTN FileSize; 2011 UINT8 *FileBuffer; 2012 UINTN NumBytesRead; 2013 UINT32 CurrentFileAlignment; 2014 EFI_STATUS Status; 2015 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress; 2016 UINT8 VtfHeaderChecksum; 2017 UINT8 VtfFileChecksum; 2018 UINT8 FileState; 2019 UINT32 TailSize; 2020 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2021 EFI_FFS_FILE_TAIL TailValue; 2022 #endif 2023 // 2024 // Verify input parameters. 2025 // 2026 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) { 2027 return EFI_INVALID_PARAMETER; 2028 } 2029 // 2030 // Read the file to add 2031 // 2032 NewFile = fopen (FvInfo->FvFiles[Index], "rb"); 2033 2034 if (NewFile == NULL) { 2035 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading"); 2036 return EFI_ABORTED; 2037 } 2038 // 2039 // Get the file size 2040 // 2041 FileSize = _filelength (_fileno (NewFile)); 2042 2043 // 2044 // Read the file into a buffer 2045 // 2046 FileBuffer = malloc (FileSize); 2047 if (FileBuffer == NULL) { 2048 Error (NULL, 0, 0, "memory allocation failure", NULL); 2049 return EFI_OUT_OF_RESOURCES; 2050 } 2051 2052 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile); 2053 2054 // 2055 // Done with the file, from this point on we will just use the buffer read. 2056 // 2057 fclose (NewFile); 2058 2059 // 2060 // Verify read successful 2061 // 2062 if (NumBytesRead != sizeof (UINT8) * FileSize) { 2063 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents"); 2064 Status = EFI_ABORTED; 2065 goto Exit; 2066 } 2067 // 2068 // Verify space exists to add the file 2069 // 2070 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { 2071 if (FvInfo->Size != (UINTN) -1) { 2072 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file"); 2073 Status = EFI_OUT_OF_RESOURCES; 2074 goto Exit; 2075 } else { 2076 // 2077 // FV Size is AUTO, increase by one block 2078 // 2079 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity); 2080 if (EFI_ERROR (Status)) { 2081 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file"); 2082 goto Exit; 2083 } 2084 } 2085 } 2086 // 2087 // Update the file state based on polarity of the FV. 2088 // 2089 UpdateFfsFileState ( 2090 (EFI_FFS_FILE_HEADER *) FileBuffer, 2091 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage 2092 ); 2093 2094 // 2095 // If we have a VTF file, add it at the top. 2096 // 2097 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) { 2098 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) { 2099 // 2100 // No previous VTF, add this one. 2101 // 2102 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize); 2103 // 2104 // Sanity check. The file MUST align appropriately 2105 // 2106 if ((((UINTN) *VtfFileImage) & 0x07) != 0) { 2107 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL); 2108 } 2109 // 2110 // copy VTF File Header 2111 // 2112 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER)); 2113 2114 // 2115 // Copy VTF body 2116 // 2117 memcpy ( 2118 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER), 2119 FileBuffer + sizeof (EFI_FFS_FILE_HEADER), 2120 FileSize - sizeof (EFI_FFS_FILE_HEADER) 2121 ); 2122 2123 // 2124 // re-calculate the VTF File Header 2125 // 2126 FileState = (*VtfFileImage)->State; 2127 (*VtfFileImage)->State = 0; 2128 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize; 2129 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0; 2130 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0; 2131 2132 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER)); 2133 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum; 2134 // 2135 // Determine if it has a tail 2136 // 2137 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 2138 TailSize = sizeof (EFI_FFS_FILE_TAIL); 2139 } else { 2140 TailSize = 0; 2141 } 2142 2143 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) { 2144 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2145 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize); 2146 #else 2147 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) ((UINTN)*VtfFileImage + sizeof (EFI_FFS_FILE_HEADER)), FileSize - TailSize - sizeof(EFI_FFS_FILE_HEADER)); 2148 #endif 2149 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum; 2150 } else { 2151 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; 2152 } 2153 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2154 // 2155 // If it has a file tail, update it 2156 // 2157 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 2158 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference)); 2159 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; 2160 } 2161 #endif 2162 (*VtfFileImage)->State = FileState; 2163 Status = EFI_SUCCESS; 2164 goto Exit; 2165 } else { 2166 // 2167 // Already found a VTF file. 2168 // 2169 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL); 2170 Status = EFI_ABORTED; 2171 goto Exit; 2172 } 2173 } 2174 // 2175 // Check if alignment is required 2176 // 2177 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); 2178 if (EFI_ERROR (Status)) { 2179 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]); 2180 Status = EFI_ABORTED; 2181 goto Exit; 2182 } 2183 // 2184 // Add pad file if necessary 2185 // 2186 while (EFI_ERROR (AddPadFile (FvImage, CurrentFileAlignment))) { 2187 if (FvInfo->Size != (UINTN) -1) { 2188 printf ("ERROR: Could not align the file data properly.\n"); 2189 Status = EFI_ABORTED; 2190 goto Exit; 2191 } else { 2192 // 2193 // FV Size is AUTO, increase by one block 2194 // 2195 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity); 2196 if (EFI_ERROR (Status)) { 2197 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file"); 2198 goto Exit; 2199 } 2200 } 2201 } 2202 2203 // 2204 // Add file 2205 // 2206 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { 2207 if (FvInfo->Size != (UINTN) -1) { 2208 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]); 2209 Status = EFI_ABORTED; 2210 goto Exit; 2211 } else { 2212 // 2213 // FV Size is AUTO, increase by one one block 2214 // 2215 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity); 2216 if (EFI_ERROR (Status)) { 2217 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file"); 2218 goto Exit; 2219 } 2220 } 2221 } 2222 2223 // 2224 // Copy the file 2225 // 2226 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); 2227 2228 // 2229 // If the file is XIP, rebase 2230 // 2231 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage); 2232 // 2233 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress); 2234 // if (EFI_ERROR(Status)) { 2235 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]); 2236 // return EFI_ABORTED; 2237 // } 2238 // 2239 // Update Symbol file 2240 // 2241 Status = AddSymFile ( 2242 CurrentFileBaseAddress, 2243 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer, 2244 SymImage, 2245 FvInfo->FvFiles[Index] 2246 ); 2247 assert (!EFI_ERROR (Status)); 2248 2249 // 2250 // Update the current pointer in the FV image 2251 // 2252 FvImage->CurrentFilePointer += FileSize; 2253 2254 // 2255 // Make next file start at QWord Boundry 2256 // 2257 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) { 2258 FvImage->CurrentFilePointer++; 2259 } 2260 2261 Exit: 2262 // 2263 // Free allocated memory. 2264 // 2265 free (FileBuffer); 2266 return Status; 2267 } 2268 2269 EFI_STATUS 2270 AddVariableBlock ( 2271 IN UINT8 *FvImage, 2272 IN UINTN Size, 2273 IN FV_INFO *FvInfo 2274 ) 2275 { 2276 EFI_FIRMWARE_VOLUME_HEADER *FvHeader; 2277 VARIABLE_STORE_HEADER *VarStoreHeader; 2278 // 2279 // Variable block should exclude FvHeader. Since the length of 2280 // FvHeader depends on the block map, which is variable length, 2281 // we could only decide the actual variable block length here. 2282 // 2283 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; 2284 FvImage = FvImage + FvHeader->HeaderLength; 2285 2286 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage; 2287 2288 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE; 2289 VarStoreHeader->Size = Size - FvHeader->HeaderLength; 2290 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED; 2291 VarStoreHeader->State = VARIABLE_STORE_HEALTHY; 2292 VarStoreHeader->Reserved = 0; 2293 VarStoreHeader->Reserved1 = 0; 2294 2295 return EFI_SUCCESS; 2296 } 2297 2298 EFI_STATUS 2299 AddEventLogBlock ( 2300 IN UINT8 *FvImage, 2301 IN UINTN Size, 2302 IN FV_INFO *FvInfo 2303 ) 2304 { 2305 return EFI_SUCCESS; 2306 } 2307 2308 EFI_STATUS 2309 AddFTWWorkingBlock ( 2310 IN UINT8 *FvImage, 2311 IN UINTN Size, 2312 IN FV_INFO *FvInfo 2313 ) 2314 { 2315 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader; 2316 UINT32 Crc32; 2317 2318 Crc32 = 0; 2319 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage; 2320 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID)); 2321 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); 2322 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32); 2323 FTWHeader->Crc = Crc32; 2324 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) { 2325 FTWHeader->WorkingBlockValid = 0; 2326 FTWHeader->WorkingBlockInvalid = 1; 2327 } else { 2328 FTWHeader->WorkingBlockValid = 1; 2329 FTWHeader->WorkingBlockInvalid = 0; 2330 } 2331 2332 return EFI_SUCCESS; 2333 } 2334 2335 EFI_STATUS 2336 AddFTWSpareBlock ( 2337 IN UINT8 *FvImage, 2338 IN UINTN Size, 2339 IN FV_INFO *FvInfo 2340 ) 2341 { 2342 return EFI_SUCCESS; 2343 } 2344 2345 EFI_STATUS 2346 GenNonFFSFv ( 2347 IN UINT8 *FvImage, 2348 IN FV_INFO *FvInfo 2349 ) 2350 /*++ 2351 2352 Routine Description: 2353 2354 This function generate the non FFS FV image, such as the working block 2355 and spare block. How each component of the FV is built is component 2356 specific. 2357 2358 Arguments: 2359 2360 FvImage The memory image of the FV to add it to. The current offset 2361 must be valid. 2362 FvInfo Pointer to information about the FV. 2363 2364 Returns: 2365 2366 EFI_SUCCESS The function completed successfully. 2367 EFI_INVALID_PARAMETER One of the input parameters was invalid. 2368 EFI_ABORTED An error occurred. 2369 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. 2370 2371 --*/ 2372 { 2373 UINTN Index; 2374 EFI_FIRMWARE_VOLUME_HEADER *FvHeader; 2375 UINT64 TotalSize; 2376 2377 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; 2378 TotalSize = 0; 2379 2380 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) { 2381 if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) { 2382 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); 2383 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) { 2384 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); 2385 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) { 2386 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); 2387 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) { 2388 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); 2389 } else { 2390 printf ("Warning: Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName); 2391 } 2392 2393 FvImage = FvImage + FvInfo->FvComponents[Index].Size; 2394 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size; 2395 } 2396 // 2397 // Index and TotalSize is zero mean there's no component, so this is an empty fv 2398 // 2399 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) { 2400 printf ("Error. Component size does not sum up to FV size.\n"); 2401 return EFI_ABORTED; 2402 } 2403 2404 return EFI_SUCCESS; 2405 } 2406 2407 EFI_STATUS 2408 PadFvImage ( 2409 IN MEMORY_FILE *FvImage, 2410 IN EFI_FFS_FILE_HEADER *VtfFileImage 2411 ) 2412 /*++ 2413 2414 Routine Description: 2415 2416 This function places a pad file between the last file in the FV and the VTF 2417 file if the VTF file exists. 2418 2419 Arguments: 2420 2421 FvImage Memory file for the FV memory image 2422 VtfFileImage The address of the VTF file. If this is the end of the FV 2423 image, no VTF exists and no pad file is needed. 2424 2425 Returns: 2426 2427 EFI_SUCCESS Completed successfully. 2428 EFI_INVALID_PARAMETER One of the input parameters was NULL. 2429 2430 --*/ 2431 { 2432 EFI_FFS_FILE_HEADER *PadFile; 2433 UINTN FileSize; 2434 2435 // 2436 // If there is no VTF or the VTF naturally follows the previous file without a 2437 // pad file, then there's nothing to do 2438 // 2439 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) { 2440 return EFI_SUCCESS; 2441 } 2442 // 2443 // Pad file starts at beginning of free space 2444 // 2445 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; 2446 2447 // 2448 // write header 2449 // 2450 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); 2451 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID)); 2452 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; 2453 PadFile->Attributes = 0; 2454 2455 // 2456 // FileSize includes the EFI_FFS_FILE_HEADER 2457 // 2458 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer; 2459 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF); 2460 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8); 2461 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16); 2462 2463 // 2464 // Fill in checksums and state, must be zero during checksum calculation. 2465 // 2466 PadFile->IntegrityCheck.Checksum.Header = 0; 2467 PadFile->IntegrityCheck.Checksum.File = 0; 2468 PadFile->State = 0; 2469 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); 2470 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { 2471 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2472 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize); 2473 #else 2474 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER)), FileSize - sizeof (EFI_FFS_FILE_HEADER)); 2475 #endif 2476 } else { 2477 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; 2478 } 2479 2480 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; 2481 2482 UpdateFfsFileState ( 2483 (EFI_FFS_FILE_HEADER *) PadFile, 2484 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage 2485 ); 2486 // 2487 // Update the current FV pointer 2488 // 2489 FvImage->CurrentFilePointer = FvImage->Eof; 2490 2491 return EFI_SUCCESS; 2492 } 2493 2494 EFI_STATUS 2495 UpdateResetVector ( 2496 IN MEMORY_FILE *FvImage, 2497 IN FV_INFO *FvInfo, 2498 IN EFI_FFS_FILE_HEADER *VtfFile 2499 ) 2500 /*++ 2501 2502 Routine Description: 2503 2504 This parses the FV looking for the PEI core and then plugs the address into 2505 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to 2506 complete an IA32 Bootstrap FV. 2507 2508 Arguments: 2509 2510 FvImage Memory file for the FV memory image 2511 FvInfo Information read from INF file. 2512 VtfFile Pointer to the VTF file in the FV image. 2513 2514 Returns: 2515 2516 EFI_SUCCESS Function Completed successfully. 2517 EFI_ABORTED Error encountered. 2518 EFI_INVALID_PARAMETER A required parameter was NULL. 2519 EFI_NOT_FOUND PEI Core file not found. 2520 2521 --*/ 2522 { 2523 EFI_FFS_FILE_HEADER *PeiCoreFile; 2524 EFI_FFS_FILE_HEADER *SecCoreFile; 2525 EFI_STATUS Status; 2526 EFI_FILE_SECTION_POINTER Pe32Section; 2527 UINT32 EntryPoint; 2528 UINT32 BaseOfCode; 2529 UINT16 MachineType; 2530 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress; 2531 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress; 2532 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr; 2533 UINT32 *Ia32ResetAddressPtr; 2534 UINT8 *BytePointer; 2535 UINT8 *BytePointer2; 2536 UINT16 *WordPointer; 2537 UINT16 CheckSum; 2538 UINTN Index; 2539 EFI_FFS_FILE_STATE SavedState; 2540 UINT32 TailSize; 2541 UINT64 FitAddress; 2542 FIT_TABLE *FitTablePtr; 2543 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2544 EFI_FFS_FILE_TAIL TailValue; 2545 #endif 2546 // 2547 // Verify input parameters 2548 // 2549 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { 2550 return EFI_INVALID_PARAMETER; 2551 } 2552 // 2553 // Initialize FV library 2554 // 2555 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage); 2556 2557 // 2558 // Verify VTF file 2559 // 2560 Status = VerifyFfsFile (VtfFile); 2561 if (EFI_ERROR (Status)) { 2562 return EFI_INVALID_PARAMETER; 2563 } 2564 // 2565 // Find the PEI Core 2566 // 2567 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); 2568 if (EFI_ERROR (Status) || PeiCoreFile == NULL) { 2569 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL); 2570 return EFI_ABORTED; 2571 } 2572 // 2573 // PEI Core found, now find PE32 or TE section 2574 // 2575 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); 2576 if (Status == EFI_NOT_FOUND) { 2577 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section); 2578 } 2579 2580 if (EFI_ERROR (Status)) { 2581 Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL); 2582 return EFI_ABORTED; 2583 } 2584 2585 Status = GetPe32Info ( 2586 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), 2587 &EntryPoint, 2588 &BaseOfCode, 2589 &MachineType 2590 ); 2591 2592 if (EFI_ERROR (Status)) { 2593 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL); 2594 return EFI_ABORTED; 2595 } 2596 // 2597 // Physical address is FV base + offset of PE32 + offset of the entry point 2598 // 2599 PeiCorePhysicalAddress = FvInfo->BaseAddress; 2600 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; 2601 PeiCorePhysicalAddress += EntryPoint; 2602 2603 if (MachineType == EFI_IMAGE_MACHINE_IA64) { 2604 // 2605 // Update PEI_CORE address 2606 // 2607 // 2608 // Set the uncached attribute bit in the physical address 2609 // 2610 PeiCorePhysicalAddress |= 0x8000000000000000; 2611 2612 // 2613 // Check if address is aligned on a 16 byte boundary 2614 // 2615 if (PeiCorePhysicalAddress & 0xF) { 2616 printf ( 2617 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", 2618 PeiCorePhysicalAddress 2619 ); 2620 return EFI_ABORTED; 2621 } 2622 // 2623 // First Get the FIT table address 2624 // 2625 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF; 2626 2627 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress)); 2628 2629 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress); 2630 2631 if (!EFI_ERROR (Status)) { 2632 UpdateFitCheckSum (FitTablePtr); 2633 } 2634 // 2635 // Find the Sec Core 2636 // 2637 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); 2638 if (EFI_ERROR (Status) || SecCoreFile == NULL) { 2639 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL); 2640 return EFI_ABORTED; 2641 } 2642 // 2643 // Sec Core found, now find PE32 section 2644 // 2645 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); 2646 if (EFI_ERROR (Status)) { 2647 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL); 2648 return EFI_ABORTED; 2649 } 2650 2651 Status = GetPe32Info ( 2652 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), 2653 &EntryPoint, 2654 &BaseOfCode, 2655 &MachineType 2656 ); 2657 if (EFI_ERROR (Status)) { 2658 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL); 2659 return EFI_ABORTED; 2660 } 2661 // 2662 // Physical address is FV base + offset of PE32 + offset of the entry point 2663 // 2664 SecCorePhysicalAddress = FvInfo->BaseAddress; 2665 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; 2666 SecCorePhysicalAddress += EntryPoint; 2667 2668 // 2669 // Update SEC_CORE address 2670 // 2671 // 2672 // Set the uncached attribute bit in the physical address 2673 // 2674 SecCorePhysicalAddress |= 0x8000000000000000; 2675 2676 // 2677 // Update the address 2678 // 2679 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET); 2680 *SecCoreEntryAddressPtr = SecCorePhysicalAddress; 2681 2682 // 2683 // Check if address is aligned on a 16 byte boundary 2684 // 2685 if (SecCorePhysicalAddress & 0xF) { 2686 printf ( 2687 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", 2688 SecCorePhysicalAddress 2689 ); 2690 return EFI_ABORTED; 2691 } 2692 } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) || 2693 (MachineType == EFI_IMAGE_MACHINE_X64)) { 2694 // 2695 // Get the location to update 2696 // 2697 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); 2698 2699 // 2700 // Write lower 32 bits of physical address 2701 // 2702 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; 2703 2704 // 2705 // Update the BFV base address 2706 // 2707 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); 2708 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); 2709 2710 CheckSum = 0x0000; 2711 2712 // 2713 // Update the Startup AP in the FVH header block ZeroVector region. 2714 // 2715 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); 2716 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray; 2717 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { 2718 *BytePointer++ = *BytePointer2++; 2719 } 2720 // 2721 // Calculate the checksum 2722 // 2723 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage); 2724 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { 2725 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); 2726 WordPointer++; 2727 } 2728 // 2729 // Update the checksum field 2730 // 2731 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); 2732 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2); 2733 WordPointer = (UINT16 *) BytePointer; 2734 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); 2735 } else { 2736 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType); 2737 return EFI_ABORTED; 2738 } 2739 // 2740 // Determine if it has an FFS file tail. 2741 // 2742 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 2743 TailSize = sizeof (EFI_FFS_FILE_TAIL); 2744 } else { 2745 TailSize = 0; 2746 } 2747 // 2748 // Now update file checksum 2749 // 2750 SavedState = VtfFile->State; 2751 VtfFile->IntegrityCheck.Checksum.File = 0; 2752 VtfFile->State = 0; 2753 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) { 2754 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2755 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( 2756 (UINT8 *) VtfFile, 2757 GetLength (VtfFile->Size) - TailSize 2758 ); 2759 2760 #else 2761 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( 2762 (UINT8 *) ((UINTN)VtfFile + sizeof (EFI_FFS_FILE_HEADER)), 2763 GetLength (VtfFile->Size) - TailSize - sizeof (EFI_FFS_FILE_HEADER) 2764 ); 2765 #endif 2766 } else { 2767 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; 2768 } 2769 2770 VtfFile->State = SavedState; 2771 2772 #if (PI_SPECIFICATION_VERSION < 0x00010000) 2773 // 2774 // Update tail if present 2775 // 2776 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 2777 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference)); 2778 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; 2779 } 2780 #endif 2781 return EFI_SUCCESS; 2782 } 2783 2784 EFI_STATUS 2785 GetPe32Info ( 2786 IN UINT8 *Pe32, 2787 OUT UINT32 *EntryPoint, 2788 OUT UINT32 *BaseOfCode, 2789 OUT UINT16 *MachineType 2790 ) 2791 /*++ 2792 2793 Routine Description: 2794 2795 Retrieves the PE32 entry point offset and machine type from PE image or TE image. 2796 See EfiImage.h for machine types. The entry point offset is from the beginning 2797 of the PE32 buffer passed in. 2798 2799 Arguments: 2800 2801 Pe32 Beginning of the PE32. 2802 EntryPoint Offset from the beginning of the PE32 to the image entry point. 2803 BaseOfCode Base address of code. 2804 MachineType Magic number for the machine type. 2805 2806 Returns: 2807 2808 EFI_SUCCESS Function completed successfully. 2809 EFI_ABORTED Error encountered. 2810 EFI_INVALID_PARAMETER A required parameter was NULL. 2811 EFI_UNSUPPORTED The operation is unsupported. 2812 2813 --*/ 2814 { 2815 EFI_IMAGE_DOS_HEADER *DosHeader; 2816 EFI_IMAGE_NT_HEADERS *NtHeader; 2817 EFI_TE_IMAGE_HEADER *TeHeader; 2818 2819 // 2820 // Verify input parameters 2821 // 2822 if (Pe32 == NULL) { 2823 return EFI_INVALID_PARAMETER; 2824 } 2825 2826 // 2827 // First check whether it is one TE Image. 2828 // 2829 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32; 2830 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 2831 // 2832 // By TeImage Header to get output 2833 // 2834 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; 2835 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; 2836 *MachineType = TeHeader->Machine; 2837 } else { 2838 // 2839 // Then check whether 2840 // is the DOS header 2841 // 2842 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32; 2843 2844 // 2845 // Verify DOS header is expected 2846 // 2847 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { 2848 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic); 2849 return EFI_UNSUPPORTED; 2850 } 2851 // 2852 // Immediately following is the NT header. 2853 // 2854 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew); 2855 2856 // 2857 // Verify NT header is expected 2858 // 2859 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { 2860 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature); 2861 return EFI_UNSUPPORTED; 2862 } 2863 // 2864 // Get output 2865 // 2866 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; 2867 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode; 2868 *MachineType = NtHeader->FileHeader.Machine; 2869 } 2870 2871 // 2872 // Verify machine type is supported 2873 // 2874 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && 2875 *MachineType != EFI_IMAGE_MACHINE_IA64 && 2876 *MachineType != EFI_IMAGE_MACHINE_X64) { 2877 printf ("ERROR: Unrecognized machine type in the PE32 file.\n"); 2878 return EFI_UNSUPPORTED; 2879 } 2880 2881 return EFI_SUCCESS; 2882 } 2883 // 2884 // Exposed function implementations (prototypes are defined in GenFvImageLib.h) 2885 // 2886 EFI_STATUS 2887 GenerateFvImage ( 2888 IN CHAR8 *InfFileImage, 2889 IN UINTN InfFileSize, 2890 OUT UINT8 **FvImage, 2891 OUT UINTN *FvImageSize, 2892 OUT CHAR8 **FvFileName, 2893 OUT UINT8 **SymImage, 2894 OUT UINTN *SymImageSize, 2895 OUT CHAR8 **SymFileName 2896 ) 2897 /*++ 2898 2899 Routine Description: 2900 2901 This is the main function which will be called from application. 2902 2903 Arguments: 2904 2905 InfFileImage Buffer containing the INF file contents. 2906 InfFileSize Size of the contents of the InfFileImage buffer. 2907 FvImage Pointer to the FV image created. 2908 FvImageSize Size of the FV image created and pointed to by FvImage. 2909 FvFileName Requested name for the FV file. 2910 SymImage Pointer to the Sym image created. 2911 SymImageSize Size of the Sym image created and pointed to by SymImage. 2912 SymFileName Requested name for the Sym file. 2913 2914 Returns: 2915 2916 EFI_SUCCESS Function completed successfully. 2917 EFI_OUT_OF_RESOURCES Could not allocate required resources. 2918 EFI_ABORTED Error encountered. 2919 EFI_INVALID_PARAMETER A required parameter was NULL. 2920 2921 --*/ 2922 { 2923 EFI_STATUS Status; 2924 MEMORY_FILE InfMemoryFile; 2925 MEMORY_FILE FvImageMemoryFile; 2926 MEMORY_FILE SymImageMemoryFile; 2927 FV_INFO FvInfo; 2928 UINTN Index; 2929 EFI_FIRMWARE_VOLUME_HEADER *FvHeader; 2930 EFI_FFS_FILE_HEADER *VtfFileImage; 2931 UINTN FvImageCapacity; 2932 2933 // 2934 // Check for invalid parameter 2935 // 2936 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) { 2937 return EFI_INVALID_PARAMETER; 2938 } 2939 // 2940 // Initialize file structures 2941 // 2942 InfMemoryFile.FileImage = InfFileImage; 2943 InfMemoryFile.CurrentFilePointer = InfFileImage; 2944 InfMemoryFile.Eof = InfFileImage + InfFileSize; 2945 2946 // 2947 // Parse the FV inf file for header information 2948 // 2949 Status = ParseFvInf (&InfMemoryFile, &FvInfo); 2950 if (EFI_ERROR (Status)) { 2951 printf ("ERROR: Could not parse the input INF file.\n"); 2952 return EFI_ABORTED; 2953 } 2954 // 2955 // Update the file name return values 2956 // 2957 strcpy (*FvFileName, FvInfo.FvName); 2958 strcpy (*SymFileName, FvInfo.SymName); 2959 2960 // 2961 // Calculate the FV size 2962 // 2963 if (FvInfo.Size != (UINTN) -1) { 2964 *FvImageSize = FvInfo.Size; 2965 FvImageCapacity = FvInfo.Size; 2966 } else { 2967 // 2968 // For auto size, set default as one block 2969 // 2970 FvInfo.FvBlocks[0].NumBlocks = 1; 2971 *FvImageSize = FvInfo.FvBlocks[0].BlockLength; 2972 FvImageCapacity = FV_CAPACITY_INCREASE_UNIT; 2973 } 2974 2975 // 2976 // Allocate the FV 2977 // 2978 *FvImage = malloc (FvImageCapacity); 2979 if (*FvImage == NULL) { 2980 return EFI_OUT_OF_RESOURCES; 2981 } 2982 // 2983 // Allocate space for symbol file storage 2984 // 2985 *SymImage = malloc (SYMBOL_FILE_SIZE); 2986 if (*SymImage == NULL) { 2987 return EFI_OUT_OF_RESOURCES; 2988 } 2989 // 2990 // Initialize the FV to the erase polarity 2991 // 2992 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) { 2993 memset (*FvImage, -1, FvImageCapacity); 2994 } else { 2995 memset (*FvImage, 0, FvImageCapacity); 2996 } 2997 // 2998 // Initialize FV header 2999 // 3000 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage; 3001 3002 // 3003 // Initialize the zero vector to all zeros. 3004 // 3005 memset (FvHeader->ZeroVector, 0, 16); 3006 3007 // 3008 // Copy the FFS GUID 3009 // 3010 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID)); 3011 3012 FvHeader->FvLength = *FvImageSize; 3013 FvHeader->Signature = EFI_FVH_SIGNATURE; 3014 FvHeader->Attributes = FvInfo.FvAttributes; 3015 #if (PI_SPECIFICATION_VERSION < 0x00010000) 3016 FvHeader->Revision = EFI_FVH_REVISION; 3017 FvHeader->Reserved[0] = 0; 3018 FvHeader->Reserved[1] = 0; 3019 FvHeader->Reserved[2] = 0; 3020 #else 3021 FvHeader->Revision = EFI_FVH_PI_REVISION; 3022 FvHeader->ExtHeaderOffset = 0; 3023 FvHeader->Reserved[0] = 0; 3024 #endif 3025 // 3026 // Copy firmware block map 3027 // 3028 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) { 3029 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks; 3030 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength; 3031 } 3032 // 3033 // Add block map terminator 3034 // 3035 FvHeader->FvBlockMap[Index].NumBlocks = 0; 3036 FvHeader->FvBlockMap[Index].BlockLength = 0; 3037 3038 // 3039 // Complete the header 3040 // 3041 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage); 3042 FvHeader->Checksum = 0; 3043 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); 3044 3045 // 3046 // If there is no FFS file, find and generate each components of the FV 3047 // 3048 if (FvInfo.FvFiles[0][0] == 0) { 3049 Status = GenNonFFSFv (*FvImage, &FvInfo); 3050 if (EFI_ERROR (Status)) { 3051 printf ("ERROR: Could not generate NonFFS FV.\n"); 3052 free (*FvImage); 3053 return EFI_ABORTED; 3054 } 3055 3056 return EFI_SUCCESS; 3057 } 3058 // 3059 // Initialize our "file" view of the buffer 3060 // 3061 FvImageMemoryFile.FileImage = *FvImage; 3062 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength; 3063 FvImageMemoryFile.Eof = *FvImage +*FvImageSize; 3064 3065 // 3066 // Initialize our "file" view of the symbol file. 3067 // 3068 SymImageMemoryFile.FileImage = *SymImage; 3069 SymImageMemoryFile.CurrentFilePointer = *SymImage; 3070 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE; 3071 3072 // 3073 // Initialize the FV library. 3074 // 3075 InitializeFvLib (FvImageMemoryFile.FileImage, *FvImageSize); 3076 3077 // 3078 // Files start on 8 byte alignments, so move to the next 8 byte aligned 3079 // address. For now, just assert if it isn't. Currently FV header is 3080 // always a multiple of 8 bytes. 3081 // BUGBUG: Handle this better 3082 // 3083 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0); 3084 3085 // 3086 // Initialize the VTF file address. 3087 // 3088 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; 3089 3090 // 3091 // Add files to FV 3092 // 3093 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) { 3094 // 3095 // Add the file 3096 // 3097 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile, &FvImageCapacity); 3098 3099 // 3100 // Update FvImageSize and FvImage as they may be changed in AddFile routine 3101 // 3102 if (FvInfo.Size == (UINTN) -1) { 3103 *FvImageSize = FvInfo.FvBlocks[0].NumBlocks * FvInfo.FvBlocks[0].BlockLength; 3104 *FvImage = FvImageMemoryFile.FileImage; 3105 } 3106 3107 // 3108 // Exit if error detected while adding the file 3109 // 3110 if (EFI_ERROR (Status)) { 3111 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]); 3112 free (*FvImage); 3113 return EFI_ABORTED; 3114 } 3115 } 3116 // 3117 // If there is a VTF file, some special actions need to occur. 3118 // 3119 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) { 3120 // 3121 // Pad from the end of the last file to the beginning of the VTF file. 3122 // 3123 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); 3124 if (EFI_ERROR (Status)) { 3125 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n"); 3126 free (*FvImage); 3127 return EFI_ABORTED; 3128 } 3129 // 3130 // Update reset vector (SALE_ENTRY for IPF) 3131 // Now for IA32 and IA64 platform, the fv which has bsf file must have the 3132 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the 3133 // reset vector. If the PEI Core is found, the VTF file will probably get 3134 // corrupted by updating the entry point. 3135 // 3136 if ((FvInfo.BaseAddress + *FvImageSize) == FV_IMAGES_TOP_ADDRESS) { 3137 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage); 3138 if (EFI_ERROR(Status)) { 3139 printf ("ERROR: Could not update the reset vector.\n"); 3140 free (*FvImage); 3141 return EFI_ABORTED; 3142 } 3143 } 3144 } 3145 // 3146 // Determine final Sym file size 3147 // 3148 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage; 3149 3150 return EFI_SUCCESS; 3151 } 3152 3153 EFI_STATUS 3154 UpdatePeiCoreEntryInFit ( 3155 IN FIT_TABLE *FitTablePtr, 3156 IN UINT64 PeiCorePhysicalAddress 3157 ) 3158 /*++ 3159 3160 Routine Description: 3161 3162 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from 3163 Sec to Pei Core 3164 3165 Arguments: 3166 3167 FitTablePtr - The pointer of FIT_TABLE. 3168 PeiCorePhysicalAddress - The address of Pei Core entry. 3169 3170 Returns: 3171 3172 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. 3173 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. 3174 3175 --*/ 3176 { 3177 FIT_TABLE *TmpFitPtr; 3178 UINTN Index; 3179 UINTN NumFitComponents; 3180 3181 TmpFitPtr = FitTablePtr; 3182 NumFitComponents = TmpFitPtr->CompSize; 3183 3184 for (Index = 0; Index < NumFitComponents; Index++) { 3185 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) { 3186 TmpFitPtr->CompAddress = PeiCorePhysicalAddress; 3187 return EFI_SUCCESS; 3188 } 3189 3190 TmpFitPtr++; 3191 } 3192 3193 return EFI_NOT_FOUND; 3194 } 3195 3196 VOID 3197 UpdateFitCheckSum ( 3198 IN FIT_TABLE *FitTablePtr 3199 ) 3200 /*++ 3201 3202 Routine Description: 3203 3204 This function is used to update the checksum for FIT. 3205 3206 3207 Arguments: 3208 3209 FitTablePtr - The pointer of FIT_TABLE. 3210 3211 Returns: 3212 3213 None. 3214 3215 --*/ 3216 { 3217 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) { 3218 FitTablePtr->CheckSum = 0; 3219 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16); 3220 } 3221 } 3222