1 /** @file 2 This file contains functions required to generate a boot strap file (BSF) also 3 known as the Volume Top File (VTF) 4 5 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials are licensed and made available 7 under the terms and conditions of the BSD License which accompanies this 8 distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 // 17 // 18 // 19 #include <FvLib.h> 20 #include <Common/UefiBaseTypes.h> 21 #include "GenVtf.h" 22 #include <Guid/PiFirmwareFileSystem.h> 23 #include "CommonLib.h" 24 #include "EfiUtilityMsgs.h" 25 26 // 27 // Global variables 28 // 29 UINTN SectionOptionFlag = 0; 30 UINTN SectionCompFlag = 0; 31 32 UINT64 DebugLevel; 33 BOOLEAN DebugMode; 34 35 BOOLEAN QuietMode = FALSE; 36 37 BOOLEAN VTF_OUTPUT = FALSE; 38 CHAR8 *OutFileName1; 39 CHAR8 *OutFileName2; 40 CHAR8 *SymFileName; 41 42 CHAR8 **TokenStr; 43 CHAR8 **OrgStrTokPtr; 44 45 PARSED_VTF_INFO *FileListPtr; 46 PARSED_VTF_INFO *FileListHeadPtr; 47 48 VOID *Vtf1Buffer; 49 VOID *Vtf1EndBuffer; 50 VOID *Vtf2Buffer; 51 VOID *Vtf2EndBuffer; 52 53 UINTN ValidLineNum = 0; 54 UINTN ValidFFDFileListNum = 0; 55 56 // 57 // Section Description and their number of occurences in *.INF file 58 // 59 UINTN NumFvFiles = 0; 60 UINTN SectionOptionNum = 0; 61 62 // 63 // Global flag which will check for VTF Present, if yes then will be used 64 // to decide about adding FFS header to pad data 65 // 66 BOOLEAN VTFPresent = FALSE; 67 BOOLEAN SecondVTF = FALSE; 68 69 // 70 // Address related information 71 // 72 UINT64 Fv1BaseAddress = 0; 73 UINT64 Fv2BaseAddress = 0; 74 UINT64 Fv1EndAddress = 0; 75 UINT64 Fv2EndAddress = 0; 76 UINT32 Vtf1TotalSize = SIZE_TO_OFFSET_PAL_A_END; 77 UINT64 Vtf1LastStartAddress = 0; 78 UINT32 Vtf2TotalSize = 0; 79 UINT64 Vtf2LastStartAddress = 0; 80 81 UINT32 BufferToTop = 0; 82 83 // 84 // IA32 Reset Vector Bin name 85 // 86 CHAR8 IA32BinFile[FILE_NAME_SIZE]; 87 88 // 89 // Function Implementations 90 // 91 EFI_STATUS 92 ConvertVersionInfo ( 93 IN CHAR8 *Str, 94 IN OUT UINT8 *MajorVer, 95 IN OUT UINT8 *MinorVer 96 ) 97 /*++ 98 Routine Description: 99 100 This function split version to major version and minor version 101 102 Arguments: 103 104 Str - String representing in form XX.XX 105 MajorVer - The major version 106 MinorVer - The minor version 107 108 Returns: 109 110 EFI_SUCCESS - The function completed successfully. 111 112 --*/ 113 { 114 CHAR8 TemStr[5] = "0000"; 115 unsigned Major; 116 unsigned Minor; 117 UINTN Length; 118 119 Major = 0; 120 Minor = 0; 121 122 if (strstr (Str, ".") != NULL) { 123 sscanf ( 124 Str, 125 "%02x.%02x", 126 &Major, 127 &Minor 128 ); 129 } else { 130 Length = strlen(Str); 131 if (Length < 4) { 132 strncpy (TemStr + 4 - Length, Str, Length); 133 } else { 134 strncpy (TemStr, Str + Length - 4, 4); 135 } 136 137 sscanf ( 138 TemStr, 139 "%02x%02x", 140 &Major, 141 &Minor 142 ); 143 } 144 145 *MajorVer = (UINT8) Major; 146 *MinorVer = (UINT8) Minor; 147 return EFI_SUCCESS; 148 } 149 150 VOID 151 TrimLine ( 152 IN CHAR8 *Line 153 ) 154 /*++ 155 Routine Description: 156 157 This function cleans up the line by removing all whitespace and 158 comments 159 160 Arguments: 161 162 Line - The pointer of the string 163 164 Returns: 165 166 None 167 168 --*/ 169 { 170 CHAR8 TmpLine[FILE_NAME_SIZE]; 171 CHAR8 Char; 172 CHAR8 *Ptr0; 173 UINTN Index; 174 UINTN Index2; 175 176 // 177 // Change '#' to '//' for Comment style 178 // 179 if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) { 180 Line[Ptr0 - Line] = 0; 181 } 182 183 // 184 // Initialize counters 185 // 186 Index = 0; 187 Index2 = 0; 188 189 while ((Char = Line[Index]) != 0) { 190 if ((Char != ' ') && (Char != '\t') && (Char != '\n') && (Char != '\r')) { 191 TmpLine[Index2++] = Char; 192 } 193 Index++; 194 } 195 196 TmpLine[Index2] = 0; 197 strcpy (Line, TmpLine); 198 } 199 200 VOID 201 ValidLineCount ( 202 IN FILE *Fp 203 ) 204 /*++ 205 206 Routine Description: 207 208 This function calculated number of valid lines in a input file. 209 210 Arguments: 211 212 Fp - Pointer to a file handle which has been opened. 213 214 Returns: 215 216 None 217 218 --*/ 219 { 220 CHAR8 Buff[FILE_NAME_SIZE]; 221 while (fgets(Buff, sizeof (Buff), Fp)) { 222 TrimLine (Buff); 223 if (Buff[0] == 0) { 224 continue; 225 } 226 ValidLineNum++; 227 } 228 } 229 230 EFI_STATUS 231 ParseInputFile ( 232 IN FILE *Fp 233 ) 234 /*++ 235 236 Routine Description: 237 238 This function parses the input file and tokenize the string 239 240 Arguments: 241 242 Fp - Pointer to a file handle which has been opened. 243 244 Returns: 245 246 None 247 248 --*/ 249 { 250 CHAR8 *Token; 251 CHAR8 Buff[FILE_NAME_SIZE + 1]; 252 CHAR8 Delimit[] = "="; 253 254 Buff [FILE_NAME_SIZE] = '\0'; 255 Token = NULL; 256 257 while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) { 258 TrimLine (Buff); 259 if (Buff[0] == 0) { 260 continue; 261 } 262 Token = strtok (Buff, Delimit); 263 while (Token != NULL) { 264 strcpy (*TokenStr, Token); 265 TokenStr ++; 266 Token = strtok (NULL, Delimit); 267 } 268 } 269 return EFI_SUCCESS; 270 } 271 272 EFI_STATUS 273 InitializeComps ( 274 VOID 275 ) 276 /*++ 277 278 Routine Description: 279 280 This function initializes the relevant global variable which is being 281 used to store the information retrieved from INF file. This also initializes 282 the VTF symbol file. 283 284 Arguments: 285 286 None 287 288 Returns: 289 290 EFI_SUCCESS - The function completed successfully 291 EFI_OUT_OF_RESOURCES - Malloc failed. 292 293 --*/ 294 { 295 296 FileListPtr = malloc (sizeof (PARSED_VTF_INFO)); 297 298 if (FileListPtr == NULL) { 299 return EFI_OUT_OF_RESOURCES; 300 } 301 302 FileListHeadPtr = FileListPtr; 303 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO)); 304 FileListPtr->NextVtfInfo = NULL; 305 306 remove (SymFileName); 307 return EFI_SUCCESS; 308 } 309 310 VOID 311 ParseAndUpdateComponents ( 312 IN PARSED_VTF_INFO *VtfInfo 313 ) 314 /*++ 315 316 Routine Description: 317 318 This function initializes the relevant global variable which is being 319 used to store the information retrieved from INF file. 320 321 Arguments: 322 323 VtfInfo - A pointer to the VTF Info Structure 324 325 326 Returns: 327 328 None 329 330 --*/ 331 { 332 UINT64 StringValue; 333 334 while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) { 335 336 if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) { 337 TokenStr++; 338 if (strnicmp (*TokenStr, "F", 1) == 0) { 339 VtfInfo->LocationType = FIRST_VTF; 340 } else if (strnicmp (*TokenStr, "S", 1) == 0) { 341 VtfInfo->LocationType = SECOND_VTF; 342 } else { 343 VtfInfo->LocationType = NONE; 344 } 345 } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) { 346 TokenStr++; 347 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) { 348 Error (NULL, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr); 349 return ; 350 } 351 352 VtfInfo->CompType = (UINT8) StringValue; 353 } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) { 354 TokenStr++; 355 if (strnicmp (*TokenStr, "-", 1) == 0) { 356 VtfInfo->VersionPresent = FALSE; 357 VtfInfo->MajorVer = 0; 358 VtfInfo->MinorVer = 0; 359 } else { 360 VtfInfo->VersionPresent = TRUE; 361 ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer); 362 } 363 } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) { 364 TokenStr++; 365 strcpy (VtfInfo->CompBinName, *TokenStr); 366 } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) { 367 TokenStr++; 368 strcpy (VtfInfo->CompSymName, *TokenStr); 369 } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) { 370 TokenStr++; 371 if (strnicmp (*TokenStr, "-", 1) == 0) { 372 VtfInfo->PreferredSize = FALSE; 373 VtfInfo->CompSize = 0; 374 } else { 375 VtfInfo->PreferredSize = TRUE; 376 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) { 377 Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr); 378 return ; 379 } 380 381 VtfInfo->CompSize = (UINTN) StringValue; 382 } 383 384 } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) { 385 TokenStr++; 386 if (strnicmp (*TokenStr, "1", 1) == 0) { 387 VtfInfo->CheckSumRequired = 1; 388 } else if (strnicmp (*TokenStr, "0", 1) == 0) { 389 VtfInfo->CheckSumRequired = 0; 390 } else { 391 Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'."); 392 } 393 } 394 395 TokenStr++; 396 if (*TokenStr == NULL) { 397 break; 398 } 399 } 400 } 401 402 VOID 403 InitializeInFileInfo ( 404 VOID 405 ) 406 /*++ 407 408 Routine Description: 409 410 This function intializes the relevant global variable which is being 411 used to store the information retrieved from INF file. 412 413 Arguments: 414 415 NONE 416 417 Returns: 418 419 NONE 420 421 --*/ 422 { 423 424 SectionOptionFlag = 0; 425 SectionCompFlag = 0; 426 TokenStr = OrgStrTokPtr; 427 428 while (*TokenStr != NULL) { 429 if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) { 430 SectionOptionFlag = 1; 431 SectionCompFlag = 0; 432 } 433 434 if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 0) { 435 if (FileListPtr == NULL) { 436 FileListPtr = FileListHeadPtr; 437 } 438 439 SectionCompFlag = 1; 440 SectionOptionFlag = 0; 441 TokenStr++; 442 } 443 444 if (SectionOptionFlag) { 445 if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) { 446 TokenStr++; 447 strcpy (IA32BinFile, *TokenStr); 448 } 449 } 450 451 if (SectionCompFlag) { 452 if (stricmp (*TokenStr, "COMP_NAME") == 0) { 453 TokenStr++; 454 strcpy (FileListPtr->CompName, *TokenStr); 455 TokenStr++; 456 ParseAndUpdateComponents (FileListPtr); 457 } 458 459 if (*TokenStr != NULL) { 460 FileListPtr->NextVtfInfo = malloc (sizeof (PARSED_VTF_INFO)); 461 if (FileListPtr->NextVtfInfo == NULL) { 462 Error (NULL, 0, 4003, "Resource", "Out of memory resources.", NULL); 463 break; 464 } 465 FileListPtr = FileListPtr->NextVtfInfo; 466 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO)); 467 FileListPtr->NextVtfInfo = NULL; 468 continue; 469 } else { 470 break; 471 } 472 } 473 474 TokenStr++; 475 } 476 } 477 478 EFI_STATUS 479 GetVtfRelatedInfoFromInfFile ( 480 IN FILE *FilePointer 481 ) 482 /*++ 483 484 Routine Description: 485 486 This function reads the input file, parse it and create a list of tokens 487 which is parsed and used, to intialize the data related to VTF 488 489 Arguments: 490 491 FileName - FileName which needed to be read to parse data 492 493 Returns: 494 495 EFI_ABORTED - Error in opening file 496 EFI_INVALID_PARAMETER - File doesn't contain any valid information 497 EFI_OUT_OF_RESOURCES - Malloc Failed 498 EFI_SUCCESS - The function completed successfully 499 500 --*/ 501 { 502 FILE *Fp; 503 UINTN Index; 504 UINTN Index1; 505 EFI_STATUS Status; 506 507 Status = EFI_SUCCESS; 508 Fp = FilePointer; 509 if (Fp == NULL) { 510 Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!"); 511 return EFI_ABORTED; 512 } 513 514 ValidLineCount (Fp); 515 516 if (ValidLineNum == 0) { 517 Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!"); 518 return EFI_INVALID_PARAMETER; 519 } 520 521 TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1)); 522 523 if (TokenStr == NULL) { 524 return EFI_OUT_OF_RESOURCES; 525 } 526 527 memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1))); 528 OrgStrTokPtr = TokenStr; 529 530 for (Index = 0; Index < (2 * ValidLineNum); Index++) { 531 *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE); 532 533 if (*TokenStr == NULL) { 534 Status = EFI_OUT_OF_RESOURCES; 535 goto ParseFileError; 536 } 537 538 memset (*TokenStr, 0, FILE_NAME_SIZE); 539 TokenStr++; 540 } 541 542 TokenStr = OrgStrTokPtr; 543 fseek (Fp, 0L, SEEK_SET); 544 545 Status = InitializeComps (); 546 547 if (Status != EFI_SUCCESS) { 548 goto ParseFileError; 549 } 550 551 Status = ParseInputFile (Fp); 552 if (Status != EFI_SUCCESS) { 553 goto ParseFileError; 554 } 555 556 InitializeInFileInfo (); 557 558 ParseFileError: 559 560 for (Index1 = 0; Index1 < Index; Index1 ++) { 561 free (OrgStrTokPtr[Index1]); 562 } 563 564 free (OrgStrTokPtr); 565 566 return Status; 567 } 568 569 VOID 570 GetRelativeAddressInVtfBuffer ( 571 IN UINT64 Address, 572 IN OUT UINTN *RelativeAddress, 573 IN LOC_TYPE LocType 574 ) 575 /*++ 576 577 Routine Description: 578 579 This function checks for the address alignmnet for specified data boundary. In 580 case the address is not aligned, it returns FALSE and the amount of data in 581 terms of byte needed to adjust to get the boundary alignmnet. If data is 582 aligned, TRUE will be returned. 583 584 Arguments: 585 586 Address - The address of the flash map space 587 RelativeAddress - The relative address of the Buffer 588 LocType - The type of the VTF 589 590 591 Returns: 592 593 594 --*/ 595 { 596 UINT64 TempAddress; 597 UINT8 *LocalBuff; 598 599 if (LocType == FIRST_VTF) { 600 LocalBuff = (UINT8 *) Vtf1EndBuffer; 601 TempAddress = Fv1EndAddress - Address; 602 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress; 603 } else { 604 LocalBuff = (UINT8 *) Vtf2EndBuffer; 605 TempAddress = Fv2EndAddress - Address; 606 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress; 607 } 608 } 609 610 EFI_STATUS 611 GetComponentVersionInfo ( 612 IN OUT PARSED_VTF_INFO *VtfInfo, 613 IN UINT8 *Buffer 614 ) 615 /*++ 616 Routine Description: 617 618 This function will extract the version information from File 619 620 Arguments: 621 622 VtfInfo - A Pointer to the VTF Info Structure 623 Buffer - A Pointer to type UINT8 624 625 Returns: 626 627 EFI_SUCCESS - The function completed successfully 628 EFI_INVALID_PARAMETER - The parameter is invalid 629 630 --*/ 631 { 632 UINT16 VersionInfo; 633 EFI_STATUS Status; 634 635 switch (VtfInfo->CompType) { 636 637 case COMP_TYPE_FIT_PAL_A: 638 case COMP_TYPE_FIT_PAL_B: 639 memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16)); 640 VtfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8); 641 VtfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF); 642 Status = EFI_SUCCESS; 643 break; 644 645 default: 646 Status = EFI_INVALID_PARAMETER; 647 break; 648 } 649 650 return Status; 651 } 652 653 BOOLEAN 654 CheckAddressAlignment ( 655 IN UINT64 Address, 656 IN UINT64 AlignmentData, 657 IN OUT UINT64 *AlignAdjustByte 658 ) 659 /*++ 660 661 Routine Description: 662 663 This function checks for the address alignmnet for specified data boundary. In 664 case the address is not aligned, it returns FALSE and the amount of data in 665 terms of byte needed to adjust to get the boundary alignmnet. If data is 666 aligned, TRUE will be returned. 667 668 Arguments: 669 670 Address - Pointer to buffer containing byte data of component. 671 AlignmentData - DataSize for which address needed to be aligned 672 AlignAdjustByte - Number of bytes needed to adjust alignment. 673 674 Returns: 675 676 TRUE - Address is aligned to specific data size boundary 677 FALSE - Address in not aligned to specified data size boundary 678 - Add/Subtract AlignAdjustByte to aling the address. 679 680 --*/ 681 { 682 // 683 // Check if the assigned address is on address boundary. If not, it will 684 // return the remaining byte required to adjust the address for specified 685 // address boundary 686 // 687 *AlignAdjustByte = (Address % AlignmentData); 688 689 if (*AlignAdjustByte == 0) { 690 return TRUE; 691 } else { 692 return FALSE; 693 } 694 } 695 696 EFI_STATUS 697 GetFitTableStartAddress ( 698 IN OUT FIT_TABLE **FitTable 699 ) 700 /*++ 701 702 Routine Description: 703 704 Get the FIT table start address in VTF Buffer 705 706 Arguments: 707 708 FitTable - Pointer to available fit table where new component can be added 709 710 Returns: 711 712 EFI_SUCCESS - The function completed successfully 713 714 --*/ 715 { 716 UINT64 FitTableAdd; 717 UINT64 FitTableAddOffset; 718 UINTN RelativeAddress; 719 720 // 721 // Read the Fit Table address from Itanium-based address map. 722 // 723 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD); 724 725 // 726 // Translate this Itanium-based address in terms of local buffer address which 727 // contains the image for Boot Strapped File. The relative address will be 728 // the address of fit table VTF buffer. 729 // 730 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF); 731 FitTableAdd = *(UINTN *) RelativeAddress; 732 733 // 734 // The FitTableAdd is the extracted Itanium based address pointing to FIT 735 // table. The relative address will return its actual location in VTF 736 // Buffer. 737 // 738 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF); 739 740 *FitTable = (FIT_TABLE *) RelativeAddress; 741 742 return EFI_SUCCESS; 743 } 744 745 EFI_STATUS 746 GetNextAvailableFitPtr ( 747 IN FIT_TABLE **FitPtr 748 ) 749 /*++ 750 751 Routine Description: 752 753 Get the FIT table address and locate the free space in fit where we can add 754 new component. In this process, this function locates the fit table using 755 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec) 756 and locate the available location in FIT table to be used by new components. 757 If there are any Fit table which areg not being used contains ComponentType 758 field as 0x7F. If needed we can change this and spec this out. 759 760 Arguments: 761 762 FitPtr - Pointer to available fit table where new component can be added 763 764 Returns: 765 766 EFI_SUCCESS - The function completed successfully 767 768 --*/ 769 { 770 FIT_TABLE *TmpFitPtr; 771 UINT64 FitTableAdd; 772 UINT64 FitTableAddOffset; 773 UINTN Index; 774 UINTN NumFitComponents; 775 UINTN RelativeAddress; 776 777 // 778 // Read the Fit Table address from Itanium-based address map. 779 // 780 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD); 781 782 // 783 // Translate this Itanium-based address in terms of local buffer address which 784 // contains the image for Boot Strapped File. The relative address will be 785 // the address of fit table VTF buffer. 786 // 787 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF); 788 FitTableAdd = *(UINTN *) RelativeAddress; 789 790 // 791 // The FitTableAdd is the extracted Itanium based address pointing to FIT 792 // table. The relative address will return its actual location in VTF 793 // Buffer. 794 // 795 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF); 796 797 TmpFitPtr = (FIT_TABLE *) RelativeAddress; 798 NumFitComponents = TmpFitPtr->CompSize; 799 800 for (Index = 0; Index < NumFitComponents; Index++) { 801 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) { 802 *FitPtr = TmpFitPtr; 803 break; 804 } 805 806 TmpFitPtr++; 807 } 808 809 return EFI_SUCCESS; 810 } 811 812 int 813 CompareItems ( 814 IN const VOID *Arg1, 815 IN const VOID *Arg2 816 ) 817 /*++ 818 819 Routine Description: 820 821 This function is used by qsort to sort the FIT table based upon Component 822 Type in their incresing order. 823 824 Arguments: 825 826 Arg1 - Pointer to Arg1 827 Arg2 - Pointer to Arg2 828 829 Returns: 830 831 None 832 833 --*/ 834 { 835 if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) { 836 return 1; 837 } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) { 838 return -1; 839 } else { 840 return 0; 841 } 842 } 843 844 VOID 845 SortFitTable ( 846 IN VOID 847 ) 848 /*++ 849 850 Routine Description: 851 852 This function is used by qsort to sort the FIT table based upon Component 853 Type in their incresing order. 854 855 Arguments: 856 857 VOID 858 859 Returns: 860 861 None 862 863 --*/ 864 { 865 FIT_TABLE *FitTable; 866 FIT_TABLE *TmpFitPtr; 867 UINTN NumFitComponents; 868 UINTN Index; 869 870 GetFitTableStartAddress (&FitTable); 871 TmpFitPtr = FitTable; 872 NumFitComponents = 0; 873 for (Index = 0; Index < FitTable->CompSize; Index++) { 874 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) { 875 NumFitComponents += 1; 876 } 877 TmpFitPtr++; 878 } 879 qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems); 880 } 881 882 VOID 883 UpdateFitEntryForFwVolume ( 884 IN UINT64 Size 885 ) 886 /*++ 887 888 Routine Description: 889 890 This function updates the information about Firmware Volume in FIT TABLE. 891 This FIT table has to be immediately below the PAL_A Start and it contains 892 component type and address information. Other information can't be 893 created this time so we would need to fix it up.. 894 895 896 Arguments: 897 898 Size - Firmware Volume Size 899 900 Returns: 901 902 VOID 903 904 --*/ 905 { 906 FIT_TABLE *CompFitPtr; 907 UINTN RelativeAddress; 908 909 // 910 // FV Fit table will be located at PAL_A Startaddress - 16 byte location 911 // 912 Vtf1LastStartAddress -= 0x10; 913 Vtf1TotalSize += 0x10; 914 915 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF); 916 917 CompFitPtr = (FIT_TABLE *) RelativeAddress; 918 CompFitPtr->CompAddress = Fv1BaseAddress; 919 920 // 921 // Since we don't have any information about its location in Firmware Volume, 922 // initialize address to 0. This will be updated once Firmware Volume is 923 // being build and its current address will be fixed in FIT table. Currently 924 // we haven't implemented it so far and working on architectural clarafication 925 // 926 // 927 // Firmware Volume Size in 16 byte block 928 // 929 CompFitPtr->CompSize = ((UINT32) Size) / 16; 930 931 // 932 // Since Firmware Volume does not exist by the time we create this FIT info 933 // this should be fixedup from Firmware Volume creation tool. We haven't 934 // worked out a method so far. 935 // 936 CompFitPtr->CompVersion = MAKE_VERSION (0, 0); 937 938 // 939 // Since we don't have any info about this file, we are making sure that 940 // checksum is not needed. 941 // 942 CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT); 943 944 // 945 // Since non VTF component will reside outside the VTF, we will not have its 946 // binary image while creating VTF, hence we will not perform checksum at 947 // this time. Once Firmware Volume is being created which will contain this 948 // VTF, it will fix the FIT table for all the non VTF component and hence 949 // checksum 950 // 951 CompFitPtr->CheckSum = 0; 952 } 953 954 EFI_STATUS 955 UpdateFitEntryForNonVTFComp ( 956 IN PARSED_VTF_INFO *VtfInfo 957 ) 958 /*++ 959 960 Routine Description: 961 962 This function updates the information about non VTF component in FIT TABLE. 963 Since non VTF componets binaries are not part of VTF binary, we would still 964 be required to update its location information in Firmware Volume, inside 965 FIT table. 966 967 Arguments: 968 969 VtfInfo - Pointer to VTF Info Structure 970 971 Returns: 972 973 EFI_ABORTED - The function fails to update the component in FIT 974 EFI_SUCCESS - The function completed successfully 975 976 --*/ 977 { 978 FIT_TABLE *CompFitPtr; 979 980 // 981 // Scan the FIT table for available space 982 // 983 GetNextAvailableFitPtr (&CompFitPtr); 984 if (CompFitPtr == NULL) { 985 Error (NULL, 0, 5003, "Invalid", "Can't update this component in FIT"); 986 return EFI_ABORTED; 987 } 988 989 // 990 // Since we don't have any information about its location in Firmware Volume, 991 // initialize address to 0. This will be updated once Firmware Volume is 992 // being build and its current address will be fixed in FIT table 993 // 994 CompFitPtr->CompAddress = 0; 995 CompFitPtr->CompSize = VtfInfo->CompSize; 996 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); 997 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); 998 999 // 1000 // Since non VTF component will reside outside the VTF, we will not have its 1001 // binary image while creating VTF, hence we will not perform checksum at 1002 // this time. Once Firmware Volume is being created which will contain this 1003 // VTF, it will fix the FIT table for all the non VTF component and hence 1004 // checksum 1005 // 1006 CompFitPtr->CheckSum = 0; 1007 1008 // 1009 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base 1010 // address of Firmware Volume in which this VTF will be attached. 1011 // 1012 if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) { 1013 CompFitPtr->CompAddress = Fv1BaseAddress; 1014 } 1015 1016 return EFI_SUCCESS; 1017 } 1018 1019 // 1020 // !!!WARNING 1021 // This function is updating the SALE_ENTRY in Itanium address space as per SAL 1022 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI 1023 // CORE moves in Firmware Volume, we would need to modify this function to be 1024 // used with a API which will detect PEICORE component while building Firmware 1025 // Volume and update its entry in FIT table as well as in Itanium address space 1026 // as per Intel?Itanium(TM) SAL address space 1027 // 1028 EFI_STATUS 1029 UpdateEntryPoint ( 1030 IN PARSED_VTF_INFO *VtfInfo, 1031 IN UINT64 *CompStartAddress 1032 ) 1033 /*++ 1034 1035 Routine Description: 1036 1037 This function updated the architectural entry point in IPF, SALE_ENTRY. 1038 1039 Arguments: 1040 1041 VtfInfo - Pointer to VTF Info Structure 1042 CompStartAddress - Pointer to Component Start Address 1043 1044 Returns: 1045 1046 EFI_INVALID_PARAMETER - The parameter is invalid 1047 EFI_SUCCESS - The function completed successfully 1048 1049 --*/ 1050 { 1051 UINTN RelativeAddress; 1052 UINT64 SalEntryAdd; 1053 FILE *Fp; 1054 UINTN Offset; 1055 1056 CHAR8 Buff[FILE_NAME_SIZE]; 1057 CHAR8 Buff1[10]; 1058 CHAR8 Buff2[10]; 1059 CHAR8 OffsetStr[30]; 1060 CHAR8 Buff3[10]; 1061 CHAR8 Buff4[10]; 1062 CHAR8 Buff5[10]; 1063 CHAR8 Token[50]; 1064 1065 Fp = fopen (LongFilePath (VtfInfo->CompSymName), "rb"); 1066 1067 if (Fp == NULL) { 1068 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName); 1069 return EFI_INVALID_PARAMETER; 1070 } 1071 1072 while (fgets (Buff, sizeof (Buff), Fp) != NULL) { 1073 fscanf ( 1074 Fp, 1075 "%s %s %s %s %s %s %s", 1076 Buff1, 1077 Buff2, 1078 OffsetStr, 1079 Buff3, 1080 Buff4, 1081 Buff5, 1082 Token 1083 ); 1084 if (strnicmp (Token, "SALE_ENTRY", 10) == 0) { 1085 break; 1086 } 1087 } 1088 1089 Offset = strtoul (OffsetStr, NULL, 16); 1090 1091 *CompStartAddress += Offset; 1092 SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT); 1093 1094 GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF); 1095 1096 memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64)); 1097 1098 if (Fp != NULL) { 1099 fclose (Fp); 1100 } 1101 1102 return EFI_SUCCESS; 1103 } 1104 1105 EFI_STATUS 1106 CreateAndUpdateComponent ( 1107 IN PARSED_VTF_INFO *VtfInfo 1108 ) 1109 /*++ 1110 1111 Routine Description: 1112 1113 This function reads the binary file for each components and update them 1114 in VTF Buffer as well as in FIT table. If the component is located in non 1115 VTF area, only the FIT table address will be updated 1116 1117 Arguments: 1118 1119 VtfInfo - Pointer to Parsed Info 1120 1121 Returns: 1122 1123 EFI_SUCCESS - The function completed successful 1124 EFI_ABORTED - Aborted due to one of the many reasons like: 1125 (a) Component Size greater than the specified size. 1126 (b) Error opening files. 1127 1128 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint() 1129 EFI_OUT_OF_RESOURCES Memory allocation failure. 1130 1131 --*/ 1132 { 1133 EFI_STATUS Status; 1134 UINT64 CompStartAddress; 1135 UINT64 FileSize; 1136 UINT64 NumAdjustByte; 1137 UINT8 *Buffer; 1138 FILE *Fp; 1139 FIT_TABLE *CompFitPtr; 1140 BOOLEAN Aligncheck; 1141 1142 if (VtfInfo->LocationType == NONE) { 1143 UpdateFitEntryForNonVTFComp (VtfInfo); 1144 return EFI_SUCCESS; 1145 } 1146 1147 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb"); 1148 1149 if (Fp == NULL) { 1150 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName); 1151 return EFI_ABORTED; 1152 } 1153 1154 FileSize = _filelength (fileno (Fp)); 1155 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) { 1156 1157 // 1158 // BUGBUG: Satish to correct 1159 // 1160 FileSize -= SIZE_OF_PAL_HEADER; 1161 } 1162 1163 if (VtfInfo->PreferredSize) { 1164 if (FileSize > VtfInfo->CompSize) { 1165 Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size."); 1166 return EFI_ABORTED; 1167 } 1168 1169 FileSize = VtfInfo->CompSize; 1170 } 1171 1172 Buffer = malloc ((UINTN) FileSize); 1173 if (Buffer == NULL) { 1174 return EFI_OUT_OF_RESOURCES; 1175 } 1176 memset (Buffer, 0, (UINTN) FileSize); 1177 1178 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) { 1179 1180 // 1181 // Read first 64 bytes of PAL header and use it to find version info 1182 // 1183 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp); 1184 1185 // 1186 // PAL header contains the version info. Currently, we will use the header 1187 // to read version info and then discard. 1188 // 1189 if (!VtfInfo->VersionPresent) { 1190 GetComponentVersionInfo (VtfInfo, Buffer); 1191 } 1192 } 1193 1194 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp); 1195 fclose (Fp); 1196 1197 // 1198 // If it is non PAL_B component, pass the entire buffer to get the version 1199 // info and implement any specific case inside GetComponentVersionInfo. 1200 // 1201 if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) { 1202 if (!VtfInfo->VersionPresent) { 1203 GetComponentVersionInfo (VtfInfo, Buffer); 1204 } 1205 } 1206 1207 if (VtfInfo->LocationType == SECOND_VTF) { 1208 1209 CompStartAddress = (Vtf2LastStartAddress - FileSize); 1210 } else { 1211 CompStartAddress = (Vtf1LastStartAddress - FileSize); 1212 } 1213 1214 if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) { 1215 Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte); 1216 } else { 1217 Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte); 1218 } 1219 1220 if (!Aligncheck) { 1221 CompStartAddress -= NumAdjustByte; 1222 } 1223 1224 if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) { 1225 Vtf2LastStartAddress = CompStartAddress; 1226 Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte); 1227 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF); 1228 } else if (VtfInfo->LocationType == FIRST_VTF) { 1229 Vtf1LastStartAddress = CompStartAddress; 1230 Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte); 1231 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF); 1232 } else { 1233 Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!"); 1234 return EFI_INVALID_PARAMETER; 1235 } 1236 1237 if (EFI_ERROR (Status)) { 1238 return EFI_ABORTED; 1239 } 1240 1241 GetNextAvailableFitPtr (&CompFitPtr); 1242 1243 CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT; 1244 if ((FileSize % 16) != 0) { 1245 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16."); 1246 return EFI_INVALID_PARAMETER; 1247 } 1248 //assert ((FileSize % 16) == 0); 1249 CompFitPtr->CompSize = (UINT32) (FileSize / 16); 1250 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); 1251 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); 1252 if (VtfInfo->CheckSumRequired) { 1253 CompFitPtr->CheckSum = 0; 1254 CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize); 1255 } 1256 1257 // 1258 // Free the buffer 1259 // 1260 if (Buffer) { 1261 free (Buffer); 1262 } 1263 1264 // 1265 // Update the SYM file for this component based on it's start address. 1266 // 1267 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize); 1268 if (EFI_ERROR (Status)) { 1269 1270 // 1271 // At this time, SYM files are not required, so continue on error. 1272 // 1273 } 1274 1275 // !!!!!!!!!!!!!!!!!!!!! 1276 // BUGBUG: 1277 // This part of the code is a temporary line since PEICORE is going to be inside 1278 // VTF till we work out how to determine the SALE_ENTRY through it. We will need 1279 // to clarify so many related questions 1280 // !!!!!!!!!!!!!!!!!!!!!!! 1281 1282 if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) { 1283 Status = UpdateEntryPoint (VtfInfo, &CompStartAddress); 1284 } 1285 1286 return Status; 1287 } 1288 1289 EFI_STATUS 1290 CreateAndUpdatePAL_A ( 1291 IN PARSED_VTF_INFO *VtfInfo 1292 ) 1293 /*++ 1294 1295 Routine Description: 1296 1297 This function reads the binary file for each components and update them 1298 in VTF Buffer as well as FIT table 1299 1300 Arguments: 1301 1302 VtfInfo - Pointer to Parsed Info 1303 1304 Returns: 1305 1306 EFI_ABORTED - Due to one of the following reasons: 1307 (a)Error Opening File 1308 (b)The PAL_A Size is more than specified size status 1309 One of the values mentioned below returned from 1310 call to UpdateSymFile 1311 EFI_SUCCESS - The function completed successfully. 1312 EFI_INVALID_PARAMETER - One of the input parameters was invalid. 1313 EFI_ABORTED - An error occurred.UpdateSymFile 1314 EFI_OUT_OF_RESOURCES - Memory allocation failed. 1315 1316 --*/ 1317 { 1318 EFI_STATUS Status; 1319 UINT64 PalStartAddress; 1320 UINT64 AbsAddress; 1321 UINTN RelativeAddress; 1322 UINT64 FileSize; 1323 UINT8 *Buffer; 1324 FILE *Fp; 1325 FIT_TABLE *PalFitPtr; 1326 1327 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb"); 1328 1329 if (Fp == NULL) { 1330 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName); 1331 return EFI_ABORTED; 1332 } 1333 1334 FileSize = _filelength (fileno (Fp)); 1335 if (FileSize < 64) { 1336 Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!"); 1337 return EFI_INVALID_PARAMETER; 1338 } 1339 FileSize -= SIZE_OF_PAL_HEADER; 1340 1341 1342 if (VtfInfo->PreferredSize) { 1343 if (FileSize > VtfInfo->CompSize) { 1344 Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size."); 1345 return EFI_ABORTED; 1346 } 1347 1348 FileSize = VtfInfo->CompSize; 1349 } 1350 1351 Buffer = malloc ((UINTN) FileSize); 1352 if (Buffer == NULL) { 1353 return EFI_OUT_OF_RESOURCES; 1354 } 1355 memset (Buffer, 0, (UINTN) FileSize); 1356 1357 // 1358 // Read, Get version Info and discard the PAL header. 1359 // 1360 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp); 1361 1362 // 1363 // Extract the version info from header of PAL_A. Once done, discrad this buffer 1364 // 1365 if (!VtfInfo->VersionPresent) { 1366 GetComponentVersionInfo (VtfInfo, Buffer); 1367 } 1368 1369 // 1370 // Read PAL_A file in a buffer 1371 // 1372 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp); 1373 fclose (Fp); 1374 1375 PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize); 1376 Vtf1LastStartAddress = PalStartAddress; 1377 Vtf1TotalSize += (UINT32) FileSize; 1378 Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF); 1379 1380 AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT; 1381 GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF); 1382 PalFitPtr = (FIT_TABLE *) RelativeAddress; 1383 PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT; 1384 //assert ((FileSize % 16) == 0); 1385 if ((FileSize % 16) != 0) { 1386 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16."); 1387 return EFI_INVALID_PARAMETER; 1388 } 1389 1390 PalFitPtr->CompSize = (UINT32) (FileSize / 16); 1391 PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); 1392 PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); 1393 if (VtfInfo->CheckSumRequired) { 1394 PalFitPtr->CheckSum = 0; 1395 PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize); 1396 } 1397 1398 if (Buffer) { 1399 free (Buffer); 1400 } 1401 1402 // 1403 // Update the SYM file for this component based on it's start address. 1404 // 1405 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize); 1406 if (EFI_ERROR (Status)) { 1407 1408 // 1409 // At this time, SYM files are not required, so continue on error. 1410 // 1411 } 1412 1413 return Status; 1414 } 1415 1416 EFI_STATUS 1417 CreateFitTableAndInitialize ( 1418 IN PARSED_VTF_INFO *VtfInfo 1419 ) 1420 /*++ 1421 1422 Routine Description: 1423 1424 This function creates and intializes FIT table which would be used to 1425 add component info inside this 1426 1427 Arguments: 1428 1429 VtfInfo - Pointer to Parsed Info 1430 1431 Returns: 1432 1433 EFI_ABORTED - Aborted due to no size information 1434 EFI_SUCCESS - The function completed successfully 1435 1436 --*/ 1437 { 1438 UINT64 PalFitTableAdd; 1439 UINT64 FitTableAdd; 1440 UINT64 FitTableAddressOffset; 1441 FIT_TABLE *PalFitPtr; 1442 FIT_TABLE *FitStartPtr; 1443 UINTN NumFitComp; 1444 UINTN RelativeAddress; 1445 UINTN Index; 1446 1447 if (!VtfInfo->PreferredSize) { 1448 Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information."); 1449 return EFI_ABORTED; 1450 } 1451 1452 if ((VtfInfo->CompSize % 16) != 0) { 1453 Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size."); 1454 } 1455 1456 PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT; 1457 GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF); 1458 PalFitPtr = (FIT_TABLE *) RelativeAddress; 1459 PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize); 1460 1461 FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize; 1462 FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD); 1463 GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF); 1464 *(UINT64 *) RelativeAddress = FitTableAdd; 1465 1466 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF); 1467 1468 // 1469 // Update Fit Table with FIT Signature and FIT info in first 16 bytes. 1470 // 1471 FitStartPtr = (FIT_TABLE *) RelativeAddress; 1472 1473 strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ " 1474 assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0); 1475 FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16; 1476 FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer); 1477 1478 // 1479 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also 1480 // determine what to do for things like the FV component that aren't easily checksummed. 1481 // The checksum will be done once we are done with all the componet update in the FIT 1482 // table 1483 // 1484 FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType); 1485 1486 NumFitComp = FitStartPtr->CompSize; 1487 1488 FitStartPtr++; 1489 1490 // 1491 // Intialize remaining FIT table space to UNUSED fit component type 1492 // so that when we need to create a FIT entry for a component, we can 1493 // locate a free one and use it. 1494 // 1495 for (Index = 0; Index < (NumFitComp - 1); Index++) { 1496 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED 1497 FitStartPtr++; 1498 } 1499 1500 Vtf1TotalSize += VtfInfo->CompSize; 1501 Vtf1LastStartAddress -= VtfInfo->CompSize; 1502 1503 return EFI_SUCCESS; 1504 } 1505 1506 EFI_STATUS 1507 WriteVtfBinary ( 1508 IN CHAR8 *FileName, 1509 IN UINT32 VtfSize, 1510 IN LOC_TYPE LocType 1511 ) 1512 /*++ 1513 1514 Routine Description: 1515 1516 Write Firmware Volume from memory to a file. 1517 1518 Arguments: 1519 1520 FileName - Output File Name which needed to be created/ 1521 VtfSize - FileSize 1522 LocType - The type of the VTF 1523 1524 Returns: 1525 1526 EFI_ABORTED - Returned due to one of the following resons: 1527 (a) Error Opening File 1528 (b) Failing to copy buffers 1529 EFI_SUCCESS - The fuction completes successfully 1530 1531 --*/ 1532 { 1533 FILE *Fp; 1534 UINTN NumByte; 1535 VOID *VtfBuffer; 1536 UINTN RelativeAddress; 1537 1538 if (LocType == FIRST_VTF) { 1539 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF); 1540 VtfBuffer = (VOID *) RelativeAddress; 1541 } else { 1542 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF); 1543 VtfBuffer = (VOID *) RelativeAddress; 1544 } 1545 1546 Fp = fopen (LongFilePath (FileName), "wb"); 1547 if (Fp == NULL) { 1548 Error (NULL, 0, 0001, "Error opening file", FileName); 1549 return EFI_ABORTED; 1550 } 1551 1552 NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp); 1553 1554 if (Fp) { 1555 fclose (Fp); 1556 } 1557 1558 if (NumByte != (sizeof (UINT8) * VtfSize)) { 1559 Error (NULL, 0, 0002, "Error writing file", FileName); 1560 return EFI_ABORTED; 1561 } 1562 1563 return EFI_SUCCESS; 1564 } 1565 1566 EFI_STATUS 1567 UpdateVtfBuffer ( 1568 IN UINT64 StartAddress, 1569 IN UINT8 *Buffer, 1570 IN UINT64 DataSize, 1571 IN LOC_TYPE LocType 1572 ) 1573 /*++ 1574 1575 Routine Description: 1576 1577 Update the Firmware Volume Buffer with requested buffer data 1578 1579 Arguments: 1580 1581 StartAddress - StartAddress in buffer. This number will automatically 1582 point to right address in buffer where data needed 1583 to be updated. 1584 Buffer - Buffer pointer from data will be copied to memory mapped buffer. 1585 DataSize - Size of the data needed to be copied. 1586 LocType - The type of the VTF: First or Second 1587 1588 Returns: 1589 1590 EFI_ABORTED - The input parameter is error 1591 EFI_SUCCESS - The function completed successfully 1592 1593 --*/ 1594 { 1595 UINT8 *LocalBufferPtrToWrite; 1596 1597 if (LocType == FIRST_VTF) { 1598 if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) { 1599 Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address."); 1600 return EFI_ABORTED; 1601 } 1602 1603 LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer; 1604 1605 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress); 1606 1607 } else { 1608 1609 if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) { 1610 Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress"); 1611 return EFI_ABORTED; 1612 } 1613 LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer; 1614 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress); 1615 } 1616 1617 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize); 1618 1619 return EFI_SUCCESS; 1620 } 1621 1622 EFI_STATUS 1623 UpdateFfsHeader ( 1624 IN UINT32 TotalVtfSize, 1625 IN LOC_TYPE LocType 1626 ) 1627 /*++ 1628 1629 Routine Description: 1630 1631 Update the Firmware Volume Buffer with requested buffer data 1632 1633 Arguments: 1634 1635 TotalVtfSize - Size of the VTF 1636 Fileoffset - The start of the file relative to the start of the FV. 1637 LocType - The type of the VTF 1638 1639 Returns: 1640 1641 EFI_SUCCESS - The function completed successfully 1642 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL 1643 1644 --*/ 1645 { 1646 EFI_FFS_FILE_HEADER *FileHeader; 1647 UINTN RelativeAddress; 1648 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; 1649 1650 // 1651 // Find the VTF file header location 1652 // 1653 if (LocType == FIRST_VTF) { 1654 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF); 1655 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress; 1656 } else { 1657 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF); 1658 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress; 1659 } 1660 1661 if (FileHeader == NULL) { 1662 return EFI_INVALID_PARAMETER; 1663 } 1664 1665 // 1666 // write header 1667 // 1668 memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); 1669 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID)); 1670 FileHeader->Type = EFI_FV_FILETYPE_RAW; 1671 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM; 1672 1673 // 1674 // Now FileSize includes the EFI_FFS_FILE_HEADER 1675 // 1676 FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF); 1677 FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8); 1678 FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16); 1679 1680 // 1681 // Fill in checksums and state, all three must be zero for the checksums. 1682 // 1683 FileHeader->IntegrityCheck.Checksum.Header = 0; 1684 FileHeader->IntegrityCheck.Checksum.File = 0; 1685 FileHeader->State = 0; 1686 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER)); 1687 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) (FileHeader + 1), TotalVtfSize - sizeof (EFI_FFS_FILE_HEADER)); 1688 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; 1689 1690 return EFI_SUCCESS; 1691 } 1692 1693 EFI_STATUS 1694 ValidateAddressAndSize ( 1695 IN UINT64 BaseAddress, 1696 IN UINT64 FwVolSize 1697 ) 1698 /*++ 1699 1700 Routine Description: 1701 1702 Update the Firmware Volume Buffer with requested buffer data 1703 1704 Arguments: 1705 1706 BaseAddress - Base address for the Fw Volume. 1707 1708 FwVolSize - Total Size of the FwVolume to which VTF will be attached.. 1709 1710 Returns: 1711 1712 EFI_SUCCESS - The function completed successfully 1713 EFI_UNSUPPORTED - The input parameter is error 1714 1715 --*/ 1716 { 1717 if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) { 1718 return EFI_SUCCESS; 1719 } 1720 1721 return EFI_UNSUPPORTED; 1722 } 1723 1724 EFI_STATUS 1725 UpdateIA32ResetVector ( 1726 IN CHAR8 *FileName, 1727 IN UINT64 FirstFwVSize 1728 ) 1729 /*++ 1730 1731 Routine Description: 1732 1733 Update the 16 byte IA32 Reset vector to maintain the compatibility 1734 1735 Arguments: 1736 1737 FileName - Binary file name which contains the IA32 Reset vector info.. 1738 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached.. 1739 1740 Returns: 1741 1742 EFI_SUCCESS - The function completed successfully 1743 EFI_ABORTED - Invalid File Size 1744 EFI_INVALID_PARAMETER - Bad File Name 1745 EFI_OUT_OF_RESOURCES - Memory allocation failed. 1746 1747 --*/ 1748 { 1749 UINT8 *Buffer; 1750 UINT8 *LocalVtfBuffer; 1751 UINTN FileSize; 1752 FILE *Fp; 1753 1754 if (!strcmp (FileName, "")) { 1755 return EFI_INVALID_PARAMETER; 1756 } 1757 1758 Fp = fopen (LongFilePath (FileName), "rb"); 1759 1760 if (Fp == NULL) { 1761 Error (NULL, 0, 0001, "Error opening file", FileName); 1762 return EFI_ABORTED; 1763 } 1764 1765 FileSize = _filelength (fileno (Fp)); 1766 1767 if (FileSize > 16) { 1768 return EFI_ABORTED; 1769 } 1770 1771 Buffer = malloc (FileSize); 1772 if (Buffer == NULL) { 1773 return EFI_OUT_OF_RESOURCES; 1774 } 1775 1776 fread (Buffer, sizeof (UINT8), FileSize, Fp); 1777 1778 LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT; 1779 memcpy (LocalVtfBuffer, Buffer, FileSize); 1780 1781 if (Buffer) { 1782 free (Buffer); 1783 } 1784 1785 if (Fp != NULL) { 1786 fclose (Fp); 1787 } 1788 return EFI_SUCCESS; 1789 } 1790 1791 VOID 1792 CleanUpMemory ( 1793 VOID 1794 ) 1795 /*++ 1796 1797 Routine Description: 1798 1799 This function cleans up any allocated buffer 1800 1801 Arguments: 1802 1803 NONE 1804 1805 Returns: 1806 1807 NONE 1808 1809 --*/ 1810 { 1811 PARSED_VTF_INFO *TempFileListPtr; 1812 1813 if (Vtf1Buffer) { 1814 free (Vtf1Buffer); 1815 } 1816 1817 if (Vtf2Buffer) { 1818 free (Vtf2Buffer); 1819 } 1820 1821 // 1822 // Cleanup the buffer which was allocated to read the file names from FV.INF 1823 // 1824 FileListPtr = FileListHeadPtr; 1825 while (FileListPtr != NULL) { 1826 TempFileListPtr = FileListPtr->NextVtfInfo; 1827 free (FileListPtr); 1828 FileListPtr = TempFileListPtr; 1829 } 1830 } 1831 1832 EFI_STATUS 1833 ProcessAndCreateVtf ( 1834 IN UINT64 Size 1835 ) 1836 /*++ 1837 1838 Routine Description: 1839 1840 This function process the link list created during INF file parsing 1841 and create component in VTF and updates its info in FIT table 1842 1843 Arguments: 1844 1845 Size - Size of the Firmware Volume of which, this VTF belongs to. 1846 1847 Returns: 1848 1849 EFI_UNSUPPORTED - Unknown FIT type 1850 EFI_SUCCESS - The function completed successfully 1851 1852 --*/ 1853 { 1854 EFI_STATUS Status; 1855 PARSED_VTF_INFO *ParsedInfoPtr; 1856 1857 Status = EFI_SUCCESS; 1858 1859 ParsedInfoPtr = FileListHeadPtr; 1860 1861 while (ParsedInfoPtr != NULL) { 1862 1863 switch (ParsedInfoPtr->CompType) { 1864 // 1865 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here 1866 // 1867 case COMP_TYPE_FIT_HEADER: 1868 //COMP_TYPE_FIT_HEADER 0x00 1869 Status = CreateFitTableAndInitialize (ParsedInfoPtr); 1870 break; 1871 1872 // 1873 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here 1874 // 1875 case COMP_TYPE_FIT_PAL_A: 1876 //COMP_TYPE_FIT_PAL_A 0x0F 1877 Status = CreateAndUpdatePAL_A (ParsedInfoPtr); 1878 1879 // 1880 // Based on VTF specification, once the PAL_A component has been written, 1881 // update the Firmware Volume info as FIT table. This will be utilized 1882 // to extract the Firmware Volume Start address where this VTF will be 1883 // of part. 1884 // 1885 if (Status == EFI_SUCCESS) { 1886 UpdateFitEntryForFwVolume (Size); 1887 } 1888 break; 1889 1890 case COMP_TYPE_FIT_FV_BOOT: 1891 //COMP_TYPE_FIT_FV_BOOT 0x7E 1892 // 1893 // Since FIT entry for Firmware Volume has been created and it is 1894 // located at (PAL_A start - 16 byte). So we will not process any 1895 // Firmware Volume related entry from INF file 1896 // 1897 Status = EFI_SUCCESS; 1898 break; 1899 1900 default: 1901 // 1902 // Any other component type should be handled here. This will create the 1903 // image in specified VTF and create appropriate entry about this 1904 // component in FIT Entry. 1905 // 1906 Status = CreateAndUpdateComponent (ParsedInfoPtr); 1907 if (EFI_ERROR (Status)) { 1908 Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName); 1909 return EFI_ABORTED; 1910 } else { 1911 break;} 1912 } 1913 1914 ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo; 1915 } 1916 return Status; 1917 } 1918 1919 EFI_STATUS 1920 GenerateVtfImage ( 1921 IN UINT64 StartAddress1, 1922 IN UINT64 Size1, 1923 IN UINT64 StartAddress2, 1924 IN UINT64 Size2, 1925 IN FILE *fp 1926 ) 1927 /*++ 1928 1929 Routine Description: 1930 1931 This is the main function which will be called from application. 1932 1933 Arguments: 1934 1935 StartAddress1 - The start address of the first VTF 1936 Size1 - The size of the first VTF 1937 StartAddress2 - The start address of the second VTF 1938 Size2 - The size of the second VTF 1939 fp - The pointer to BSF inf file 1940 1941 Returns: 1942 1943 EFI_OUT_OF_RESOURCES - Can not allocate memory 1944 The return value can be any of the values 1945 returned by the calls to following functions: 1946 GetVtfRelatedInfoFromInfFile 1947 ProcessAndCreateVtf 1948 UpdateIA32ResetVector 1949 UpdateFfsHeader 1950 WriteVtfBinary 1951 1952 --*/ 1953 { 1954 EFI_STATUS Status; 1955 FILE *VtfFP; 1956 1957 Status = EFI_UNSUPPORTED; 1958 VtfFP = fp; 1959 1960 if (StartAddress2 == 0) { 1961 SecondVTF = FALSE; 1962 } else { 1963 SecondVTF = TRUE; 1964 } 1965 1966 Fv1BaseAddress = StartAddress1; 1967 Fv1EndAddress = Fv1BaseAddress + Size1; 1968 if (Fv1EndAddress != 0x100000000ULL || Size1 < 0x100000) { 1969 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!"); 1970 if (Size1 < 0x100000) { 1971 Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!"); 1972 } else if (SecondVTF != TRUE) { 1973 Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!"); 1974 } 1975 Usage(); 1976 return EFI_INVALID_PARAMETER; 1977 } 1978 1979 // 1980 // The image buffer for the First VTF 1981 // 1982 Vtf1Buffer = malloc ((UINTN) Size1); 1983 if (Vtf1Buffer == NULL) { 1984 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!"); 1985 return EFI_OUT_OF_RESOURCES; 1986 } 1987 memset (Vtf1Buffer, 0x00, (UINTN) Size1); 1988 Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1; 1989 Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT; 1990 1991 if (SecondVTF) { 1992 Fv2BaseAddress = StartAddress2; 1993 Fv2EndAddress = Fv2BaseAddress + Size2; 1994 if (Fv2EndAddress != StartAddress1) { 1995 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!"); 1996 if (SecondVTF == TRUE) { 1997 Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!"); 1998 Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!"); 1999 } 2000 Usage(); 2001 return EFI_INVALID_PARAMETER; 2002 } 2003 2004 // 2005 // The image buffer for the second VTF 2006 // 2007 Vtf2Buffer = malloc ((UINTN) Size2); 2008 if (Vtf2Buffer == NULL) { 2009 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!"); 2010 return EFI_OUT_OF_RESOURCES; 2011 } 2012 memset (Vtf2Buffer, 0x00, (UINTN) Size2); 2013 Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2; 2014 Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT; 2015 } 2016 2017 Status = GetVtfRelatedInfoFromInfFile (VtfFP); 2018 2019 if (Status != EFI_SUCCESS) { 2020 Error (NULL, 0, 0003, "Error parsing file", "the input file."); 2021 CleanUpMemory (); 2022 return Status; 2023 } 2024 2025 Status = ProcessAndCreateVtf (Size1); 2026 if (Status != EFI_SUCCESS) { 2027 CleanUpMemory (); 2028 return Status; 2029 } 2030 2031 if (SectionOptionFlag) { 2032 Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize); 2033 if (Status != EFI_SUCCESS) { 2034 CleanUpMemory (); 2035 return Status; 2036 } 2037 } 2038 2039 // 2040 // Re arrange the FIT Table for Ascending order of their FIT Type.. 2041 // 2042 SortFitTable (); 2043 2044 // 2045 // All components have been updated in FIT table. Now perform the FIT table 2046 // checksum. The following function will check if Checksum is required, 2047 // if yes, then it will perform the checksum otherwise not. 2048 // 2049 CalculateFitTableChecksum (); 2050 2051 // 2052 // Write the FFS header 2053 // 2054 Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER); 2055 Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER); 2056 2057 Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF); 2058 if (Status != EFI_SUCCESS) { 2059 CleanUpMemory (); 2060 return Status; 2061 } 2062 // 2063 // Update the VTF buffer into specified VTF binary file 2064 // 2065 Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF); 2066 2067 if (SecondVTF) { 2068 Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER); 2069 Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER); 2070 Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF); 2071 if (Status != EFI_SUCCESS) { 2072 CleanUpMemory (); 2073 return Status; 2074 } 2075 2076 // 2077 // Update the VTF buffer into specified VTF binary file 2078 // 2079 Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF); 2080 } 2081 2082 CleanUpMemory (); 2083 2084 return Status; 2085 } 2086 2087 EFI_STATUS 2088 PeimFixupInFitTable ( 2089 IN UINT64 StartAddress 2090 ) 2091 /*++ 2092 2093 Routine Description: 2094 2095 This function is an entry point to fixup SAL-E entry point. 2096 2097 Arguments: 2098 2099 StartAddress - StartAddress for PEIM..... 2100 2101 Returns: 2102 2103 EFI_SUCCESS - The function completed successfully 2104 EFI_ABORTED - Error Opening File 2105 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation. 2106 2107 --*/ 2108 { 2109 EFI_STATUS Status; 2110 FILE *Fp; 2111 UINT64 *StartAddressPtr; 2112 UINTN FirstFwVSize; 2113 2114 StartAddressPtr = malloc (sizeof (UINT64)); 2115 if (StartAddressPtr == NULL) { 2116 return EFI_OUT_OF_RESOURCES; 2117 } 2118 *StartAddressPtr = StartAddress; 2119 2120 Fp = fopen (LongFilePath (OutFileName1), "rb"); 2121 2122 if (Fp == NULL) { 2123 Error (NULL, 0, 0001, "Error opening file", OutFileName1); 2124 if (StartAddressPtr) { 2125 free (StartAddressPtr); 2126 } 2127 return EFI_ABORTED; 2128 } 2129 2130 FirstFwVSize = _filelength (fileno (Fp)); 2131 fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET); 2132 fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp); 2133 2134 if (Fp) { 2135 fclose (Fp); 2136 } 2137 2138 if (StartAddressPtr) { 2139 free (StartAddressPtr); 2140 } 2141 2142 Status = EFI_SUCCESS; 2143 return Status; 2144 } 2145 2146 EFI_STATUS 2147 UpdateSymFile ( 2148 IN UINT64 BaseAddress, 2149 IN CHAR8 *DestFileName, 2150 IN CHAR8 *SourceFileName, 2151 IN UINT64 FileSize 2152 2153 ) 2154 /*++ 2155 2156 Routine Description: 2157 2158 This function adds the SYM tokens in the source file to the destination file. 2159 The SYM tokens are updated to reflect the base address. 2160 2161 Arguments: 2162 2163 BaseAddress - The base address for the new SYM tokens. 2164 DestFileName - The destination file. 2165 SourceFileName - The source file. 2166 FileSize - Size of bin file. 2167 2168 Returns: 2169 2170 EFI_SUCCESS - The function completed successfully. 2171 EFI_INVALID_PARAMETER - One of the input parameters was invalid. 2172 EFI_ABORTED - An error occurred. 2173 2174 --*/ 2175 { 2176 FILE *SourceFile; 2177 FILE *DestFile; 2178 CHAR8 Buffer[MAX_LONG_FILE_PATH]; 2179 CHAR8 Type[MAX_LONG_FILE_PATH]; 2180 CHAR8 Address[MAX_LONG_FILE_PATH]; 2181 CHAR8 Section[MAX_LONG_FILE_PATH]; 2182 CHAR8 Token[MAX_LONG_FILE_PATH]; 2183 CHAR8 BaseToken[MAX_LONG_FILE_PATH]; 2184 UINT64 TokenAddress; 2185 long StartLocation; 2186 2187 // 2188 // Verify input parameters. 2189 // 2190 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) { 2191 return EFI_INVALID_PARAMETER; 2192 } 2193 2194 // 2195 // Open the source file 2196 // 2197 SourceFile = fopen (LongFilePath (SourceFileName), "r"); 2198 if (SourceFile == NULL) { 2199 2200 // 2201 // SYM files are not required. 2202 // 2203 return EFI_SUCCESS; 2204 } 2205 2206 // 2207 // Use the file name minus extension as the base for tokens 2208 // 2209 strcpy (BaseToken, SourceFileName); 2210 strtok (BaseToken, ". \t\n"); 2211 strcat (BaseToken, "__"); 2212 2213 // 2214 // Open the destination file 2215 // 2216 DestFile = fopen (LongFilePath (DestFileName), "a+"); 2217 if (DestFile == NULL) { 2218 fclose (SourceFile); 2219 Error (NULL, 0, 0001, "Error opening file", DestFileName); 2220 return EFI_ABORTED; 2221 } 2222 2223 // 2224 // If this is the beginning of the output file, write the symbol format info. 2225 // 2226 if (fseek (DestFile, 0, SEEK_END) != 0) { 2227 fclose (SourceFile); 2228 fclose (DestFile); 2229 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file."); 2230 return EFI_ABORTED; 2231 } 2232 2233 StartLocation = ftell (DestFile); 2234 2235 if (StartLocation == 0) { 2236 fprintf (DestFile, "TEXTSYM format | V1.0\n"); 2237 } else if (StartLocation == -1) { 2238 fclose (SourceFile); 2239 fclose (DestFile); 2240 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error"); 2241 return EFI_ABORTED; 2242 } 2243 2244 // 2245 // Read the first line 2246 // 2247 if (fgets (Buffer, MAX_LONG_FILE_PATH, SourceFile) == NULL) { 2248 Buffer[0] = 0; 2249 } 2250 2251 // 2252 // Make sure it matches the expected sym format 2253 // 2254 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) { 2255 fclose (SourceFile); 2256 fclose (DestFile); 2257 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)"); 2258 return EFI_ABORTED; 2259 } 2260 2261 // 2262 // Read in the file 2263 // 2264 while (feof (SourceFile) == 0) { 2265 2266 // 2267 // Read a line 2268 // 2269 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) { 2270 2271 // 2272 // Get the token address 2273 // 2274 AsciiStringToUint64 (Address, TRUE, &TokenAddress); 2275 if (TokenAddress > FileSize) { 2276 // 2277 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them. 2278 // 2279 break; 2280 } 2281 2282 // 2283 // Add the base address, the size of the FFS file header and the size of the peim header. 2284 // 2285 TokenAddress += BaseAddress &~IPF_CACHE_BIT; 2286 2287 fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress); 2288 fprintf (DestFile, "%s | %s\n %s\n", Section, Token, BaseToken); 2289 } 2290 } 2291 2292 fclose (SourceFile); 2293 fclose (DestFile); 2294 return EFI_SUCCESS; 2295 } 2296 2297 EFI_STATUS 2298 CalculateFitTableChecksum ( 2299 VOID 2300 ) 2301 /*++ 2302 2303 Routine Description: 2304 2305 This function will perform byte checksum on the FIT table, if the the checksum required 2306 field is set to CheckSum required. If the checksum is not required then checksum byte 2307 will have value as 0;. 2308 2309 Arguments: 2310 2311 NONE 2312 2313 Returns: 2314 2315 Status - Value returned by call to CalculateChecksum8 () 2316 EFI_SUCCESS - The function completed successfully 2317 2318 --*/ 2319 { 2320 FIT_TABLE *TmpFitPtr; 2321 UINT64 FitTableAdd; 2322 UINT64 FitTableAddOffset; 2323 UINTN RelativeAddress; 2324 UINTN Size; 2325 2326 // 2327 // Read the Fit Table address from Itanium-based address map. 2328 // 2329 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD); 2330 2331 // 2332 // Translate this Itanium-based address in terms of local buffer address which 2333 // contains the image for Boot Strapped File 2334 // 2335 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF); 2336 FitTableAdd = *(UINTN *) RelativeAddress; 2337 2338 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF); 2339 2340 TmpFitPtr = (FIT_TABLE *) RelativeAddress; 2341 2342 Size = TmpFitPtr->CompSize * 16; 2343 2344 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) { 2345 TmpFitPtr->CheckSum = 0; 2346 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size); 2347 } else { 2348 TmpFitPtr->CheckSum = 0; 2349 } 2350 2351 return EFI_SUCCESS; 2352 } 2353 2354 VOID 2355 Version ( 2356 VOID 2357 ) 2358 /*++ 2359 2360 Routine Description: 2361 2362 Displays the standard utility information to SDTOUT 2363 2364 Arguments: 2365 2366 None 2367 2368 Returns: 2369 2370 None 2371 2372 --*/ 2373 { 2374 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); 2375 } 2376 2377 VOID 2378 Usage ( 2379 VOID 2380 ) 2381 /*++ 2382 2383 Routine Description: 2384 2385 Displays the utility usage syntax to STDOUT 2386 2387 Arguments: 2388 2389 None 2390 2391 Returns: 2392 2393 None 2394 2395 --*/ 2396 { 2397 // 2398 // Summary usage 2399 // 2400 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME); 2401 2402 // 2403 // Copyright declaration 2404 // 2405 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); 2406 // 2407 // Details Option 2408 // 2409 fprintf (stdout, "Options:\n"); 2410 fprintf (stdout, " -f Input_file, --filename Input_file\n\ 2411 Input_file is name of the BS Image INF file\n"); 2412 fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\ 2413 BaseAddress is the starting address of Firmware Volume\n\ 2414 where Boot Strapped Image will reside.\n"); 2415 fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\ 2416 FwVolumeSize is the size of Firmware Volume.\n"); 2417 fprintf (stdout, " -o FileName, --output FileName\n\ 2418 File will be created to store the ouput content.\n"); 2419 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); 2420 fprintf (stdout, " --version Show program's version number and exit.\n"); 2421 fprintf (stdout, " -h, --help Show this help message and exit.\n"); 2422 fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n"); 2423 fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n"); 2424 } 2425 2426 int 2427 main ( 2428 IN int argc, 2429 IN char **argv 2430 ) 2431 /*++ 2432 2433 Routine Description: 2434 2435 This utility uses GenVtf.dll to build a Boot Strap File Image which will be 2436 part of firmware volume image. 2437 2438 Arguments: 2439 2440 argc - The count of the parameters 2441 argv - The parameters 2442 2443 2444 Returns: 2445 2446 0 - No error conditions detected. 2447 1 - One or more of the input parameters is invalid. 2448 2 - A resource required by the utility was unavailable. 2449 - Most commonly this will be memory allocation or file creation. 2450 3 - GenFvImage.dll could not be loaded. 2451 4 - Error executing the GenFvImage dll. 2452 5 - Now this tool does not support the IA32 platform 2453 2454 --*/ 2455 { 2456 UINT8 Index; 2457 UINT64 StartAddress1; 2458 UINT64 StartAddress2; 2459 UINT64 FwVolSize1; 2460 UINT64 FwVolSize2; 2461 BOOLEAN FirstRoundO; 2462 BOOLEAN FirstRoundB; 2463 BOOLEAN FirstRoundS; 2464 EFI_STATUS Status; 2465 FILE *VtfFP; 2466 CHAR8 *VtfFileName; 2467 2468 SetUtilityName (UTILITY_NAME); 2469 2470 // 2471 // Initialize variables 2472 // 2473 StartAddress1 = 0; 2474 StartAddress2 = 0; 2475 FwVolSize1 = 0; 2476 FwVolSize2 = 0; 2477 FirstRoundB = TRUE; 2478 FirstRoundS = TRUE; 2479 FirstRoundO = TRUE; 2480 DebugMode = FALSE; 2481 OutFileName1 = NULL; 2482 OutFileName2 = NULL; 2483 VtfFP = NULL; 2484 DebugLevel = 0; 2485 2486 // 2487 // Verify the correct number of arguments 2488 // 2489 if (argc == 1) { 2490 Usage(); 2491 return 0; 2492 } 2493 2494 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { 2495 Usage(); 2496 return 0; 2497 } 2498 2499 if ((strcmp(argv[1], "--version") == 0)) { 2500 Version(); 2501 return 0; 2502 } 2503 2504 // 2505 // Parse the command line arguments 2506 // 2507 for (Index = 1; Index < argc; Index += 2) { 2508 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) { 2509 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') { 2510 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); 2511 goto ERROR; 2512 } 2513 // 2514 // Get the output file name 2515 // 2516 VTF_OUTPUT = TRUE; 2517 if (FirstRoundO) { 2518 // 2519 // It's the first output file name 2520 // 2521 OutFileName1 = (CHAR8 *)argv[Index+1]; 2522 FirstRoundO = FALSE; 2523 } else { 2524 // 2525 //It's the second output file name 2526 // 2527 OutFileName2 = (CHAR8 *)argv[Index+1]; 2528 } 2529 continue; 2530 } 2531 2532 if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) { 2533 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') { 2534 Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option"); 2535 goto ERROR; 2536 } 2537 // 2538 // Get the input VTF file name 2539 // 2540 VtfFileName = argv[Index+1]; 2541 VtfFP = fopen (LongFilePath (VtfFileName), "rb"); 2542 if (VtfFP == NULL) { 2543 Error (NULL, 0, 0001, "Error opening file", VtfFileName); 2544 goto ERROR; 2545 } 2546 continue; 2547 } 2548 2549 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) { 2550 if (FirstRoundB) { 2551 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1); 2552 FirstRoundB = FALSE; 2553 } else { 2554 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2); 2555 } 2556 if (Status != EFI_SUCCESS) { 2557 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]); 2558 goto ERROR; 2559 } 2560 continue; 2561 } 2562 2563 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) { 2564 if (FirstRoundS) { 2565 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1); 2566 FirstRoundS = FALSE; 2567 } else { 2568 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2); 2569 SecondVTF = TRUE; 2570 } 2571 2572 if (Status != EFI_SUCCESS) { 2573 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]); 2574 goto ERROR; 2575 } 2576 continue; 2577 } 2578 2579 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) { 2580 VerboseMode = TRUE; 2581 Index--; 2582 continue; 2583 } 2584 2585 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) { 2586 QuietMode = TRUE; 2587 Index--; 2588 continue; 2589 } 2590 2591 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) { 2592 // 2593 // debug level specified 2594 // 2595 Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel); 2596 if (EFI_ERROR (Status)) { 2597 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]); 2598 goto ERROR; 2599 } 2600 if (DebugLevel > 9) { 2601 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]); 2602 goto ERROR; 2603 } 2604 if((DebugLevel <= 9) &&(DebugLevel >= 5)) { 2605 DebugMode = TRUE; 2606 } else { 2607 DebugMode = FALSE; 2608 } 2609 continue; 2610 } 2611 2612 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]); 2613 goto ERROR; 2614 } 2615 2616 if (VtfFP == NULL) { 2617 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified"); 2618 goto ERROR; 2619 } 2620 2621 if (FirstRoundB) { 2622 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified"); 2623 goto ERROR; 2624 } 2625 2626 if (FirstRoundS) { 2627 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified"); 2628 goto ERROR; 2629 } 2630 // 2631 // All Parameters has been parsed, now set the message print level 2632 // 2633 if (QuietMode) { 2634 SetPrintLevel(40); 2635 } else if (VerboseMode) { 2636 SetPrintLevel(15); 2637 } else if (DebugMode) { 2638 SetPrintLevel(DebugLevel); 2639 } 2640 2641 if (VerboseMode) { 2642 VerboseMsg("%s tool start.\n", UTILITY_NAME); 2643 } 2644 2645 if (VTF_OUTPUT == FALSE) { 2646 if (SecondVTF == TRUE) { 2647 OutFileName1 = VTF_OUTPUT_FILE1; 2648 OutFileName2 = VTF_OUTPUT_FILE2; 2649 } else { 2650 OutFileName1 = VTF_OUTPUT_FILE1; 2651 } 2652 SymFileName = VTF_SYM_FILE; 2653 } else { 2654 INTN OutFileNameLen = strlen(OutFileName1); 2655 INTN Index; 2656 2657 for (Index = OutFileNameLen; Index > 0; --Index) { 2658 if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') { 2659 break; 2660 } 2661 } 2662 if (Index == 0) { 2663 SymFileName = VTF_SYM_FILE; 2664 } else { 2665 INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE); 2666 SymFileName = malloc(SymFileNameLen + 1); 2667 memcpy(SymFileName, OutFileName1, Index + 1); 2668 memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE)); 2669 SymFileName[SymFileNameLen] = '\0'; 2670 } 2671 if (DebugMode) { 2672 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL); 2673 } 2674 } 2675 2676 // 2677 // Call the GenVtfImage 2678 // 2679 if (DebugMode) { 2680 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL); 2681 } 2682 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP); 2683 2684 if (EFI_ERROR (Status)) { 2685 switch (Status) { 2686 2687 case EFI_INVALID_PARAMETER: 2688 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function."); 2689 break; 2690 2691 case EFI_ABORTED: 2692 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image."); 2693 break; 2694 2695 case EFI_OUT_OF_RESOURCES: 2696 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources."); 2697 break; 2698 2699 case EFI_VOLUME_CORRUPTED: 2700 Error (NULL, 0, 3000, "Invalid", "No base address was specified."); 2701 break; 2702 2703 default: 2704 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status ); 2705 break; 2706 } 2707 } 2708 ERROR: 2709 if (VtfFP != NULL) { 2710 fclose (VtfFP); 2711 } 2712 2713 if (DebugMode) { 2714 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL); 2715 } 2716 2717 if (VerboseMode) { 2718 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); 2719 } 2720 return GetUtilityStatus(); 2721 } 2722