3 Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
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.
19 This file contains functions required to generate a boot strap file (BSF)
20 also known as the Volume Top File (VTF)
28 #include <Common/UefiBaseTypes.h>
30 #include <Guid/PiFirmwareFileSystem.h>
31 #include "CommonLib.h"
32 #include "EfiUtilityMsgs.h"
37 UINTN SectionOptionFlag
= 0;
38 UINTN SectionCompFlag
= 0;
43 BOOLEAN QuietMode
= FALSE
;
45 BOOLEAN VTF_OUTPUT
= FALSE
;
53 PARSED_VTF_INFO
*FileListPtr
;
54 PARSED_VTF_INFO
*FileListHeadPtr
;
61 UINTN ValidLineNum
= 0;
62 UINTN ValidFFDFileListNum
= 0;
65 // Section Description and their number of occurences in *.INF file
68 UINTN SectionOptionNum
= 0;
71 // Global flag which will check for VTF Present, if yes then will be used
72 // to decide about adding FFS header to pad data
74 BOOLEAN VTFPresent
= FALSE
;
75 BOOLEAN SecondVTF
= FALSE
;
78 // Address related information
80 UINT64 Fv1BaseAddress
= 0;
81 UINT64 Fv2BaseAddress
= 0;
82 UINT64 Fv1EndAddress
= 0;
83 UINT64 Fv2EndAddress
= 0;
84 UINT32 Vtf1TotalSize
= SIZE_TO_OFFSET_PAL_A_END
;
85 UINT64 Vtf1LastStartAddress
= 0;
86 UINT32 Vtf2TotalSize
= 0;
87 UINT64 Vtf2LastStartAddress
= 0;
89 UINT32 BufferToTop
= 0;
92 // IA32 Reset Vector Bin name
94 CHAR8 IA32BinFile
[FILE_NAME_SIZE
];
97 // Function Implementations
102 IN OUT UINT8
*MajorVer
,
103 IN OUT UINT8
*MinorVer
108 This function converts GUID string to GUID
112 Str - String representing in form XX.XX
113 MajorVer - The major vertion
114 MinorVer - The minor vertion
118 EFI_SUCCESS - The fuction completed successfully.
130 memset (StrPtr
, 0, 40);
131 Token
= strtok (Str
, ".");
133 while (Token
!= NULL
) {
134 strcat (StrPtr
, Token
);
135 Token
= strtok (NULL
, ".");
138 Length
= strlen (StrPtr
);
146 *MajorVer
= (UINT8
) Major
;
147 *MinorVer
= (UINT8
) Minor
;
158 This function cleans up the line by removing all whitespace and
163 Line - The pointer of the string
171 CHAR8 TmpLine
[FILE_NAME_SIZE
];
178 // Change '#' to '//' for Comment style
180 if (((Ptr0
= strchr (Line
, '#')) != NULL
) || ((Ptr0
= strstr (Line
, "//")) != NULL
)) {
181 Line
[Ptr0
- Line
] = 0;
185 // Initialize counters
190 while ((Char
= Line
[Index
]) != 0) {
191 if ((Char
!= ' ') && (Char
!= '\t') && (Char
!= '\n') && (Char
!= '\r')) {
192 TmpLine
[Index2
++] = Char
;
198 strcpy (Line
, TmpLine
);
209 This function calculated number of valid lines in a input file.
213 Fp - Pointer to a file handle which has been opened.
221 CHAR8 Buff
[FILE_NAME_SIZE
];
222 while (fgets(Buff
, sizeof (Buff
), Fp
)) {
239 This function parses the input file and tokenize the string
243 Fp - Pointer to a file handle which has been opened.
252 CHAR8 Buff
[FILE_NAME_SIZE
+ 1];
253 CHAR8 Delimit
[] = "=";
255 Buff
[FILE_NAME_SIZE
] = '\0';
258 while (fgets (Buff
, FILE_NAME_SIZE
, Fp
) != NULL
) {
263 Token
= strtok (Buff
, Delimit
);
264 while (Token
!= NULL
) {
265 strcpy (*TokenStr
, Token
);
267 Token
= strtok (NULL
, Delimit
);
281 This function initializes the relevant global variable which is being
282 used to store the information retrieved from INF file. This also initializes
291 EFI_SUCCESS - The function completed successfully
292 EFI_OUT_OF_RESOURCES - Malloc failed.
297 FileListPtr
= malloc (sizeof (PARSED_VTF_INFO
));
299 if (FileListPtr
== NULL
) {
300 return EFI_OUT_OF_RESOURCES
;
303 FileListHeadPtr
= FileListPtr
;
304 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
305 FileListPtr
->NextVtfInfo
= NULL
;
307 remove (SymFileName
);
312 ParseAndUpdateComponents (
313 IN PARSED_VTF_INFO
*VtfInfo
319 This function initializes the relevant global variable which is being
320 used to store the information retrieved from INF file.
324 VtfInfo - A pointer to the VTF Info Structure
335 while (*TokenStr
!= NULL
&& (strnicmp (*TokenStr
, "COMP_NAME", 9) != 0)) {
337 if (strnicmp (*TokenStr
, "COMP_LOC", 8) == 0) {
339 if (strnicmp (*TokenStr
, "F", 1) == 0) {
340 VtfInfo
->LocationType
= FIRST_VTF
;
341 } else if (strnicmp (*TokenStr
, "S", 1) == 0) {
342 VtfInfo
->LocationType
= SECOND_VTF
;
344 VtfInfo
->LocationType
= NONE
;
346 } else if (strnicmp (*TokenStr
, "COMP_TYPE", 9) == 0) {
348 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
349 Error (NULL
, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr
);
353 VtfInfo
->CompType
= (UINT8
) StringValue
;
354 } else if (strnicmp (*TokenStr
, "COMP_VER", 8) == 0) {
356 if (strnicmp (*TokenStr
, "-", 1) == 0) {
357 VtfInfo
->VersionPresent
= FALSE
;
358 VtfInfo
->MajorVer
= 0;
359 VtfInfo
->MinorVer
= 0;
361 VtfInfo
->VersionPresent
= TRUE
;
362 ConvertVersionInfo (*TokenStr
, &VtfInfo
->MajorVer
, &VtfInfo
->MinorVer
);
364 } else if (strnicmp (*TokenStr
, "COMP_BIN", 8) == 0) {
366 strcpy (VtfInfo
->CompBinName
, *TokenStr
);
367 } else if (strnicmp (*TokenStr
, "COMP_SYM", 8) == 0) {
369 strcpy (VtfInfo
->CompSymName
, *TokenStr
);
370 } else if (strnicmp (*TokenStr
, "COMP_SIZE", 9) == 0) {
372 if (strnicmp (*TokenStr
, "-", 1) == 0) {
373 VtfInfo
->PreferredSize
= FALSE
;
374 VtfInfo
->CompSize
= 0;
376 VtfInfo
->PreferredSize
= TRUE
;
377 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
378 Error (NULL
, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr
);
382 VtfInfo
->CompSize
= (UINTN
) StringValue
;
385 } else if (strnicmp (*TokenStr
, "COMP_CS", 7) == 0) {
387 if (strnicmp (*TokenStr
, "1", 1) == 0) {
388 VtfInfo
->CheckSumRequired
= 1;
389 } else if (strnicmp (*TokenStr
, "0", 1) == 0) {
390 VtfInfo
->CheckSumRequired
= 0;
392 Error (NULL
, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
397 if (*TokenStr
== NULL
) {
404 InitializeInFileInfo (
411 This function intializes the relevant global variable which is being
412 used to store the information retrieved from INF file.
425 SectionOptionFlag
= 0;
427 TokenStr
= OrgStrTokPtr
;
429 while (*TokenStr
!= NULL
) {
430 if (strnicmp (*TokenStr
, "[OPTIONS]", 9) == 0) {
431 SectionOptionFlag
= 1;
435 if (strnicmp (*TokenStr
, "[COMPONENTS]", 12) == 0) {
436 if (FileListPtr
== NULL
) {
437 FileListPtr
= FileListHeadPtr
;
441 SectionOptionFlag
= 0;
445 if (SectionOptionFlag
) {
446 if (stricmp (*TokenStr
, "IA32_RST_BIN") == 0) {
448 strcpy (IA32BinFile
, *TokenStr
);
452 if (SectionCompFlag
) {
453 if (stricmp (*TokenStr
, "COMP_NAME") == 0) {
455 strcpy (FileListPtr
->CompName
, *TokenStr
);
457 ParseAndUpdateComponents (FileListPtr
);
460 if (*TokenStr
!= NULL
) {
461 FileListPtr
->NextVtfInfo
= malloc (sizeof (PARSED_VTF_INFO
));
462 if (FileListPtr
->NextVtfInfo
== NULL
) {
463 Error (NULL
, 0, 4003, "Resource", "Out of memory resources.", NULL
);
466 FileListPtr
= FileListPtr
->NextVtfInfo
;
467 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
468 FileListPtr
->NextVtfInfo
= NULL
;
480 GetVtfRelatedInfoFromInfFile (
487 This function reads the input file, parse it and create a list of tokens
488 which is parsed and used, to intialize the data related to VTF
492 FileName - FileName which needed to be read to parse data
496 EFI_ABORTED - Error in opening file
497 EFI_INVALID_PARAMETER - File doesn't contain any valid information
498 EFI_OUT_OF_RESOURCES - Malloc Failed
499 EFI_SUCCESS - The function completed successfully
508 Status
= EFI_SUCCESS
;
511 Error (NULL
, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
517 if (ValidLineNum
== 0) {
518 Error (NULL
, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
519 return EFI_INVALID_PARAMETER
;
522 TokenStr
= (CHAR8
**) malloc (sizeof (UINTN
) * (2 * ValidLineNum
+ 1));
524 if (TokenStr
== NULL
) {
525 return EFI_OUT_OF_RESOURCES
;
528 memset (TokenStr
, 0, (sizeof (UINTN
) * (2 * ValidLineNum
+ 1)));
529 OrgStrTokPtr
= TokenStr
;
531 for (Index
= 0; Index
< (2 * ValidLineNum
); Index
++) {
532 *TokenStr
= (CHAR8
*)malloc (sizeof (CHAR8
) * FILE_NAME_SIZE
);
534 if (*TokenStr
== NULL
) {
535 Status
= EFI_OUT_OF_RESOURCES
;
539 memset (*TokenStr
, 0, FILE_NAME_SIZE
);
543 TokenStr
= OrgStrTokPtr
;
544 fseek (Fp
, 0L, SEEK_SET
);
546 Status
= InitializeComps ();
548 if (Status
!= EFI_SUCCESS
) {
552 Status
= ParseInputFile (Fp
);
553 if (Status
!= EFI_SUCCESS
) {
557 InitializeInFileInfo ();
561 for (Index1
= 0; Index1
< Index
; Index1
++) {
562 free (OrgStrTokPtr
[Index1
]);
571 GetRelativeAddressInVtfBuffer (
573 IN OUT UINTN
*RelativeAddress
,
580 This function checks for the address alignmnet for specified data boundary. In
581 case the address is not aligned, it returns FALSE and the amount of data in
582 terms of byte needed to adjust to get the boundary alignmnet. If data is
583 aligned, TRUE will be returned.
587 Address - The address of the flash map space
588 RelativeAddress - The relative address of the Buffer
589 LocType - The type of the VTF
600 if (LocType
== FIRST_VTF
) {
601 LocalBuff
= (UINT8
*) Vtf1EndBuffer
;
602 TempAddress
= Fv1EndAddress
- Address
;
603 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
605 LocalBuff
= (UINT8
*) Vtf2EndBuffer
;
606 TempAddress
= Fv2EndAddress
- Address
;
607 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
612 GetComponentVersionInfo (
613 IN OUT PARSED_VTF_INFO
*VtfInfo
,
619 This function will extract the version information from File
623 VtfInfo - A Pointer to the VTF Info Structure
624 Buffer - A Pointer to type UINT8
628 EFI_SUCCESS - The function completed successfully
629 EFI_INVALID_PARAMETER - The parameter is invalid
636 switch (VtfInfo
->CompType
) {
638 case COMP_TYPE_FIT_PAL_A
:
639 case COMP_TYPE_FIT_PAL_B
:
640 memcpy (&VersionInfo
, (Buffer
+ 8), sizeof (UINT16
));
641 VtfInfo
->MajorVer
= (UINT8
) ((VersionInfo
& 0xFF00) >> 8);
642 VtfInfo
->MinorVer
= (UINT8
) (VersionInfo
& 0x00FF);
643 Status
= EFI_SUCCESS
;
647 Status
= EFI_INVALID_PARAMETER
;
655 CheckAddressAlignment (
657 IN UINT64 AlignmentData
,
658 IN OUT UINT64
*AlignAdjustByte
664 This function checks for the address alignmnet for specified data boundary. In
665 case the address is not aligned, it returns FALSE and the amount of data in
666 terms of byte needed to adjust to get the boundary alignmnet. If data is
667 aligned, TRUE will be returned.
671 Address - Pointer to buffer containing byte data of component.
672 AlignmentData - DataSize for which address needed to be aligned
673 AlignAdjustByte - Number of bytes needed to adjust alignment.
677 TRUE - Address is aligned to specific data size boundary
678 FALSE - Address in not aligned to specified data size boundary
679 - Add/Subtract AlignAdjustByte to aling the address.
684 // Check if the assigned address is on address boundary. If not, it will
685 // return the remaining byte required to adjust the address for specified
688 *AlignAdjustByte
= (Address
% AlignmentData
);
690 if (*AlignAdjustByte
== 0) {
698 GetFitTableStartAddress (
699 IN OUT FIT_TABLE
**FitTable
705 Get the FIT table start address in VTF Buffer
709 FitTable - Pointer to available fit table where new component can be added
713 EFI_SUCCESS - The function completed successfully
718 UINT64 FitTableAddOffset
;
719 UINTN RelativeAddress
;
722 // Read the Fit Table address from Itanium-based address map.
724 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
727 // Translate this Itanium-based address in terms of local buffer address which
728 // contains the image for Boot Strapped File. The relative address will be
729 // the address of fit table VTF buffer.
731 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
732 FitTableAdd
= *(UINTN
*) RelativeAddress
;
735 // The FitTableAdd is the extracted Itanium based address pointing to FIT
736 // table. The relative address will return its actual location in VTF
739 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
741 *FitTable
= (FIT_TABLE
*) RelativeAddress
;
747 GetNextAvailableFitPtr (
748 IN FIT_TABLE
**FitPtr
754 Get the FIT table address and locate the free space in fit where we can add
755 new component. In this process, this function locates the fit table using
756 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
757 and locate the available location in FIT table to be used by new components.
758 If there are any Fit table which areg not being used contains ComponentType
759 field as 0x7F. If needed we can change this and spec this out.
763 FitPtr - Pointer to available fit table where new component can be added
767 EFI_SUCCESS - The function completed successfully
771 FIT_TABLE
*TmpFitPtr
;
773 UINT64 FitTableAddOffset
;
775 UINTN NumFitComponents
;
776 UINTN RelativeAddress
;
779 // Read the Fit Table address from Itanium-based address map.
781 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
784 // Translate this Itanium-based address in terms of local buffer address which
785 // contains the image for Boot Strapped File. The relative address will be
786 // the address of fit table VTF buffer.
788 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
789 FitTableAdd
= *(UINTN
*) RelativeAddress
;
792 // The FitTableAdd is the extracted Itanium based address pointing to FIT
793 // table. The relative address will return its actual location in VTF
796 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
798 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
799 NumFitComponents
= TmpFitPtr
->CompSize
;
801 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
802 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_UNUSED
) {
822 This function is used by qsort to sort the FIT table based upon Component
823 Type in their incresing order.
827 Arg1 - Pointer to Arg1
828 Arg2 - Pointer to Arg2
836 if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) > (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
838 } else if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) < (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
853 This function is used by qsort to sort the FIT table based upon Component
854 Type in their incresing order.
867 FIT_TABLE
*TmpFitPtr
;
868 UINTN NumFitComponents
;
871 GetFitTableStartAddress (&FitTable
);
872 TmpFitPtr
= FitTable
;
873 NumFitComponents
= 0;
874 for (Index
= 0; Index
< FitTable
->CompSize
; Index
++) {
875 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) != COMP_TYPE_FIT_UNUSED
) {
876 NumFitComponents
+= 1;
880 qsort ((VOID
*) FitTable
, NumFitComponents
, sizeof (FIT_TABLE
), CompareItems
);
884 UpdateFitEntryForFwVolume (
891 This function updates the information about Firmware Volume in FIT TABLE.
892 This FIT table has to be immediately below the PAL_A Start and it contains
893 component type and address information. Other information can't be
894 created this time so we would need to fix it up..
899 Size - Firmware Volume Size
907 FIT_TABLE
*CompFitPtr
;
908 UINTN RelativeAddress
;
911 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
913 Vtf1LastStartAddress
-= 0x10;
914 Vtf1TotalSize
+= 0x10;
916 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
918 CompFitPtr
= (FIT_TABLE
*) RelativeAddress
;
919 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
922 // Since we don't have any information about its location in Firmware Volume,
923 // initialize address to 0. This will be updated once Firmware Volume is
924 // being build and its current address will be fixed in FIT table. Currently
925 // we haven't implemented it so far and working on architectural clarafication
928 // Firmware Volume Size in 16 byte block
930 CompFitPtr
->CompSize
= ((UINT32
) Size
) / 16;
933 // Since Firmware Volume does not exist by the time we create this FIT info
934 // this should be fixedup from Firmware Volume creation tool. We haven't
935 // worked out a method so far.
937 CompFitPtr
->CompVersion
= MAKE_VERSION (0, 0);
940 // Since we don't have any info about this file, we are making sure that
941 // checksum is not needed.
943 CompFitPtr
->CvAndType
= CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT
);
946 // Since non VTF component will reside outside the VTF, we will not have its
947 // binary image while creating VTF, hence we will not perform checksum at
948 // this time. Once Firmware Volume is being created which will contain this
949 // VTF, it will fix the FIT table for all the non VTF component and hence
952 CompFitPtr
->CheckSum
= 0;
956 UpdateFitEntryForNonVTFComp (
957 IN PARSED_VTF_INFO
*VtfInfo
963 This function updates the information about non VTF component in FIT TABLE.
964 Since non VTF componets binaries are not part of VTF binary, we would still
965 be required to update its location information in Firmware Volume, inside
970 VtfInfo - Pointer to VTF Info Structure
974 EFI_ABORTED - The function fails to update the component in FIT
975 EFI_SUCCESS - The function completed successfully
979 FIT_TABLE
*CompFitPtr
;
982 // Scan the FIT table for available space
984 GetNextAvailableFitPtr (&CompFitPtr
);
985 if (CompFitPtr
== NULL
) {
986 Error (NULL
, 0, 5003, "Invalid", "Can't update this component in FIT");
991 // Since we don't have any information about its location in Firmware Volume,
992 // initialize address to 0. This will be updated once Firmware Volume is
993 // being build and its current address will be fixed in FIT table
995 CompFitPtr
->CompAddress
= 0;
996 CompFitPtr
->CompSize
= VtfInfo
->CompSize
;
997 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
998 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1001 // Since non VTF component will reside outside the VTF, we will not have its
1002 // binary image while creating VTF, hence we will not perform checksum at
1003 // this time. Once Firmware Volume is being created which will contain this
1004 // VTF, it will fix the FIT table for all the non VTF component and hence
1007 CompFitPtr
->CheckSum
= 0;
1010 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
1011 // address of Firmware Volume in which this VTF will be attached.
1013 if ((CompFitPtr
->CvAndType
& 0x7F) == COMP_TYPE_FIT_FV_BOOT
) {
1014 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
1022 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
1023 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
1024 // CORE moves in Firmware Volume, we would need to modify this function to be
1025 // used with a API which will detect PEICORE component while building Firmware
1026 // Volume and update its entry in FIT table as well as in Itanium address space
1027 // as per Intel?Itanium(TM) SAL address space
1031 IN PARSED_VTF_INFO
*VtfInfo
,
1032 IN UINT64
*CompStartAddress
1036 Routine Description:
1038 This function updated the architectural entry point in IPF, SALE_ENTRY.
1042 VtfInfo - Pointer to VTF Info Structure
1043 CompStartAddress - Pointer to Component Start Address
1047 EFI_INVALID_PARAMETER - The parameter is invalid
1048 EFI_SUCCESS - The function completed successfully
1052 UINTN RelativeAddress
;
1057 CHAR8 Buff
[FILE_NAME_SIZE
];
1060 CHAR8 OffsetStr
[30];
1066 Fp
= fopen (VtfInfo
->CompSymName
, "rb");
1069 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompSymName
);
1070 return EFI_INVALID_PARAMETER
;
1073 while (fgets (Buff
, sizeof (Buff
), Fp
) != NULL
) {
1076 "%s %s %s %s %s %s %s",
1085 if (strnicmp (Token
, "SALE_ENTRY", 10) == 0) {
1090 Offset
= strtoul (OffsetStr
, NULL
, 16);
1092 *CompStartAddress
+= Offset
;
1093 SalEntryAdd
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
);
1095 GetRelativeAddressInVtfBuffer (SalEntryAdd
, &RelativeAddress
, FIRST_VTF
);
1097 memcpy ((VOID
*) RelativeAddress
, (VOID
*) CompStartAddress
, sizeof (UINT64
));
1107 CreateAndUpdateComponent (
1108 IN PARSED_VTF_INFO
*VtfInfo
1112 Routine Description:
1114 This function reads the binary file for each components and update them
1115 in VTF Buffer as well as in FIT table. If the component is located in non
1116 VTF area, only the FIT table address will be updated
1120 VtfInfo - Pointer to Parsed Info
1124 EFI_SUCCESS - The function completed successful
1125 EFI_ABORTED - Aborted due to one of the many reasons like:
1126 (a) Component Size greater than the specified size.
1127 (b) Error opening files.
1129 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1130 EFI_OUT_OF_RESOURCES Memory allocation failure.
1135 UINT64 CompStartAddress
;
1138 UINT64 NumAdjustByte
;
1141 FIT_TABLE
*CompFitPtr
;
1144 if (VtfInfo
->LocationType
== NONE
) {
1145 UpdateFitEntryForNonVTFComp (VtfInfo
);
1149 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1152 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1156 FileSize
= _filelength (fileno (Fp
));
1157 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1160 // BUGBUG: Satish to correct
1162 FileSize
-= SIZE_OF_PAL_HEADER
;
1165 if (VtfInfo
->PreferredSize
) {
1166 if (FileSize
> VtfInfo
->CompSize
) {
1167 Error (NULL
, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1171 FileSize
= VtfInfo
->CompSize
;
1174 Buffer
= malloc ((UINTN
) FileSize
);
1175 if (Buffer
== NULL
) {
1176 return EFI_OUT_OF_RESOURCES
;
1178 memset (Buffer
, 0, (UINTN
) FileSize
);
1180 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1183 // Read first 64 bytes of PAL header and use it to find version info
1185 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1188 // PAL header contains the version info. Currently, we will use the header
1189 // to read version info and then discard.
1191 if (!VtfInfo
->VersionPresent
) {
1192 GetComponentVersionInfo (VtfInfo
, Buffer
);
1196 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1200 // If it is non PAL_B component, pass the entire buffer to get the version
1201 // info and implement any specific case inside GetComponentVersionInfo.
1203 if (VtfInfo
->CompType
!= COMP_TYPE_FIT_PAL_B
) {
1204 if (!VtfInfo
->VersionPresent
) {
1205 GetComponentVersionInfo (VtfInfo
, Buffer
);
1209 if (VtfInfo
->LocationType
== SECOND_VTF
) {
1211 CompStartAddress
= (Vtf2LastStartAddress
- FileSize
);
1213 CompStartAddress
= (Vtf1LastStartAddress
- FileSize
);
1216 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) {
1217 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 32 * 1024, &NumAdjustByte
);
1219 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 8, &NumAdjustByte
);
1223 CompStartAddress
-= NumAdjustByte
;
1226 if (VtfInfo
->LocationType
== SECOND_VTF
&& SecondVTF
== TRUE
) {
1227 Vtf2LastStartAddress
= CompStartAddress
;
1228 Vtf2TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1229 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, SECOND_VTF
);
1230 } else if (VtfInfo
->LocationType
== FIRST_VTF
) {
1231 Vtf1LastStartAddress
= CompStartAddress
;
1232 Vtf1TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1233 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1235 Error (NULL
, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
1236 return EFI_INVALID_PARAMETER
;
1239 if (EFI_ERROR (Status
)) {
1243 GetNextAvailableFitPtr (&CompFitPtr
);
1245 CompFitPtr
->CompAddress
= CompStartAddress
| IPF_CACHE_BIT
;
1246 if ((FileSize
% 16) != 0) {
1247 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1248 return EFI_INVALID_PARAMETER
;
1250 //assert ((FileSize % 16) == 0);
1251 CompFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1252 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1253 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1254 if (VtfInfo
->CheckSumRequired
) {
1255 CompFitPtr
->CheckSum
= 0;
1256 CompFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1267 // Update the SYM file for this component based on it's start address.
1269 Status
= UpdateSymFile (CompStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1270 if (EFI_ERROR (Status
)) {
1273 // At this time, SYM files are not required, so continue on error.
1277 // !!!!!!!!!!!!!!!!!!!!!
1279 // This part of the code is a temporary line since PEICORE is going to be inside
1280 // VTF till we work out how to determine the SALE_ENTRY through it. We will need
1281 // to clarify so many related questions
1282 // !!!!!!!!!!!!!!!!!!!!!!!
1284 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PEICORE
) {
1285 Status
= UpdateEntryPoint (VtfInfo
, &CompStartAddress
);
1292 CreateAndUpdatePAL_A (
1293 IN PARSED_VTF_INFO
*VtfInfo
1297 Routine Description:
1299 This function reads the binary file for each components and update them
1300 in VTF Buffer as well as FIT table
1304 VtfInfo - Pointer to Parsed Info
1308 EFI_ABORTED - Due to one of the following reasons:
1309 (a)Error Opening File
1310 (b)The PAL_A Size is more than specified size status
1311 One of the values mentioned below returned from
1312 call to UpdateSymFile
1313 EFI_SUCCESS - The function completed successfully.
1314 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
1315 EFI_ABORTED - An error occurred.UpdateSymFile
1316 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1321 UINT64 PalStartAddress
;
1323 UINTN RelativeAddress
;
1328 FIT_TABLE
*PalFitPtr
;
1330 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1333 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1337 FileSize
= _filelength (fileno (Fp
));
1338 if (FileSize
< 64) {
1339 Error (NULL
, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
1340 return EFI_INVALID_PARAMETER
;
1342 FileSize
-= SIZE_OF_PAL_HEADER
;
1345 if (VtfInfo
->PreferredSize
) {
1346 if (FileSize
> VtfInfo
->CompSize
) {
1347 Error (NULL
, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
1351 FileSize
= VtfInfo
->CompSize
;
1354 Buffer
= malloc ((UINTN
) FileSize
);
1355 if (Buffer
== NULL
) {
1356 return EFI_OUT_OF_RESOURCES
;
1358 memset (Buffer
, 0, (UINTN
) FileSize
);
1361 // Read, Get version Info and discard the PAL header.
1363 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1366 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1368 if (!VtfInfo
->VersionPresent
) {
1369 GetComponentVersionInfo (VtfInfo
, Buffer
);
1373 // Read PAL_A file in a buffer
1375 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1378 PalStartAddress
= Fv1EndAddress
- (SIZE_TO_OFFSET_PAL_A_END
+ FileSize
);
1379 Vtf1LastStartAddress
= PalStartAddress
;
1380 Vtf1TotalSize
+= (UINT32
) FileSize
;
1381 Status
= UpdateVtfBuffer (PalStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1383 AbsAddress
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1384 GetRelativeAddressInVtfBuffer (AbsAddress
, &RelativeAddress
, FIRST_VTF
);
1385 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1386 PalFitPtr
->CompAddress
= PalStartAddress
| IPF_CACHE_BIT
;
1387 //assert ((FileSize % 16) == 0);
1388 if ((FileSize
% 16) != 0) {
1389 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1390 return EFI_INVALID_PARAMETER
;
1393 PalFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1394 PalFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1395 PalFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1396 if (VtfInfo
->CheckSumRequired
) {
1397 PalFitPtr
->CheckSum
= 0;
1398 PalFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1406 // Update the SYM file for this component based on it's start address.
1408 Status
= UpdateSymFile (PalStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1409 if (EFI_ERROR (Status
)) {
1412 // At this time, SYM files are not required, so continue on error.
1420 CreateFitTableAndInitialize (
1421 IN PARSED_VTF_INFO
*VtfInfo
1425 Routine Description:
1427 This function creates and intializes FIT table which would be used to
1428 add component info inside this
1432 VtfInfo - Pointer to Parsed Info
1436 EFI_ABORTED - Aborted due to no size information
1437 EFI_SUCCESS - The function completed successfully
1441 UINT64 PalFitTableAdd
;
1443 UINT64 FitTableAddressOffset
;
1444 FIT_TABLE
*PalFitPtr
;
1445 FIT_TABLE
*FitStartPtr
;
1447 UINTN RelativeAddress
;
1450 if (!VtfInfo
->PreferredSize
) {
1451 Error (NULL
, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1455 if ((VtfInfo
->CompSize
% 16) != 0) {
1456 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
1459 PalFitTableAdd
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1460 GetRelativeAddressInVtfBuffer (PalFitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1461 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1462 PalFitTableAdd
= (PalFitPtr
->CompAddress
- VtfInfo
->CompSize
);
1464 FitTableAdd
= (PalFitPtr
->CompAddress
- 0x10) - VtfInfo
->CompSize
;
1465 FitTableAddressOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
1466 GetRelativeAddressInVtfBuffer (FitTableAddressOffset
, &RelativeAddress
, FIRST_VTF
);
1467 *(UINT64
*) RelativeAddress
= FitTableAdd
;
1469 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1472 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1474 FitStartPtr
= (FIT_TABLE
*) RelativeAddress
;
1476 strncpy ((CHAR8
*) &FitStartPtr
->CompAddress
, FIT_SIGNATURE
, 8); // "_FIT_ "
1477 assert (((VtfInfo
->CompSize
& 0x00FFFFFF) % 16) == 0);
1478 FitStartPtr
->CompSize
= (VtfInfo
->CompSize
& 0x00FFFFFF) / 16;
1479 FitStartPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1482 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1483 // determine what to do for things like the FV component that aren't easily checksummed.
1484 // The checksum will be done once we are done with all the componet update in the FIT
1487 FitStartPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1489 NumFitComp
= FitStartPtr
->CompSize
;
1494 // Intialize remaining FIT table space to UNUSED fit component type
1495 // so that when we need to create a FIT entry for a component, we can
1496 // locate a free one and use it.
1498 for (Index
= 0; Index
< (NumFitComp
- 1); Index
++) {
1499 FitStartPtr
->CvAndType
= 0x7F; // Initialize all with UNUSED
1503 Vtf1TotalSize
+= VtfInfo
->CompSize
;
1504 Vtf1LastStartAddress
-= VtfInfo
->CompSize
;
1517 Routine Description:
1519 Write Firmware Volume from memory to a file.
1523 FileName - Output File Name which needed to be created/
1525 LocType - The type of the VTF
1529 EFI_ABORTED - Returned due to one of the following resons:
1530 (a) Error Opening File
1531 (b) Failing to copy buffers
1532 EFI_SUCCESS - The fuction completes successfully
1539 UINTN RelativeAddress
;
1541 if (LocType
== FIRST_VTF
) {
1542 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1543 VtfBuffer
= (VOID
*) RelativeAddress
;
1545 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1546 VtfBuffer
= (VOID
*) RelativeAddress
;
1549 Fp
= fopen (FileName
, "wb");
1551 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1555 NumByte
= fwrite (VtfBuffer
, sizeof (UINT8
), (UINTN
) VtfSize
, Fp
);
1561 if (NumByte
!= (sizeof (UINT8
) * VtfSize
)) {
1562 Error (NULL
, 0, 0002, "Error writing file", FileName
);
1571 IN UINT64 StartAddress
,
1578 Routine Description:
1580 Update the Firmware Volume Buffer with requested buffer data
1584 StartAddress - StartAddress in buffer. This number will automatically
1585 point to right address in buffer where data needed
1587 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1588 DataSize - Size of the data needed to be copied.
1589 LocType - The type of the VTF: First or Second
1593 EFI_ABORTED - The input parameter is error
1594 EFI_SUCCESS - The function completed successfully
1598 UINT8
*LocalBufferPtrToWrite
;
1600 if (LocType
== FIRST_VTF
) {
1601 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf1LastStartAddress
| IPF_CACHE_BIT
)) {
1602 Error (NULL
, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
1606 LocalBufferPtrToWrite
= (UINT8
*) Vtf1EndBuffer
;
1608 LocalBufferPtrToWrite
-= (Fv1EndAddress
- StartAddress
);
1612 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf2LastStartAddress
| IPF_CACHE_BIT
)) {
1613 Error (NULL
, 0, 2000, "Invalid parameter", "Error StartAddress");
1616 LocalBufferPtrToWrite
= (UINT8
*) Vtf2EndBuffer
;
1617 LocalBufferPtrToWrite
-= (Fv2EndAddress
- StartAddress
);
1620 memcpy (LocalBufferPtrToWrite
, Buffer
, (UINTN
) DataSize
);
1627 IN UINT32 TotalVtfSize
,
1632 Routine Description:
1634 Update the Firmware Volume Buffer with requested buffer data
1638 TotalVtfSize - Size of the VTF
1639 Fileoffset - The start of the file relative to the start of the FV.
1640 LocType - The type of the VTF
1644 EFI_SUCCESS - The function completed successfully
1645 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1649 EFI_FFS_FILE_HEADER
*FileHeader
;
1650 UINTN RelativeAddress
;
1651 EFI_GUID EfiFirmwareVolumeTopFileGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1654 // Find the VTF file header location
1656 if (LocType
== FIRST_VTF
) {
1657 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1658 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1660 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1661 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1664 if (FileHeader
== NULL
) {
1665 return EFI_INVALID_PARAMETER
;
1671 memset (FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1672 memcpy (&FileHeader
->Name
, &EfiFirmwareVolumeTopFileGuid
, sizeof (EFI_GUID
));
1673 FileHeader
->Type
= EFI_FV_FILETYPE_RAW
;
1674 FileHeader
->Attributes
= FFS_ATTRIB_CHECKSUM
;
1677 // Now FileSize includes the EFI_FFS_FILE_HEADER
1679 FileHeader
->Size
[0] = (UINT8
) (TotalVtfSize
& 0x000000FF);
1680 FileHeader
->Size
[1] = (UINT8
) ((TotalVtfSize
& 0x0000FF00) >> 8);
1681 FileHeader
->Size
[2] = (UINT8
) ((TotalVtfSize
& 0x00FF0000) >> 16);
1684 // Fill in checksums and state, all three must be zero for the checksums.
1686 FileHeader
->IntegrityCheck
.Checksum
.Header
= 0;
1687 FileHeader
->IntegrityCheck
.Checksum
.File
= 0;
1688 FileHeader
->State
= 0;
1689 FileHeader
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1690 FileHeader
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) (FileHeader
+ 1), TotalVtfSize
- sizeof (EFI_FFS_FILE_HEADER
));
1691 FileHeader
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1697 ValidateAddressAndSize (
1698 IN UINT64 BaseAddress
,
1703 Routine Description:
1705 Update the Firmware Volume Buffer with requested buffer data
1709 BaseAddress - Base address for the Fw Volume.
1711 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1715 EFI_SUCCESS - The function completed successfully
1716 EFI_UNSUPPORTED - The input parameter is error
1720 if ((BaseAddress
>= 0) && (FwVolSize
> 0x40) && ((BaseAddress
+ FwVolSize
) % 8 == 0)) {
1724 return EFI_UNSUPPORTED
;
1728 UpdateIA32ResetVector (
1730 IN UINT64 FirstFwVSize
1734 Routine Description:
1736 Update the 16 byte IA32 Reset vector to maintain the compatibility
1740 FileName - Binary file name which contains the IA32 Reset vector info..
1741 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
1745 EFI_SUCCESS - The function completed successfully
1746 EFI_ABORTED - Invalid File Size
1747 EFI_INVALID_PARAMETER - Bad File Name
1748 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1753 UINT8
*LocalVtfBuffer
;
1758 if (!strcmp (FileName
, "")) {
1759 return EFI_INVALID_PARAMETER
;
1762 Fp
= fopen (FileName
, "rb");
1765 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1769 FileSize
= _filelength (fileno (Fp
));
1771 if (FileSize
> 16) {
1775 Buffer
= malloc (FileSize
);
1776 if (Buffer
== NULL
) {
1777 return EFI_OUT_OF_RESOURCES
;
1780 NumByteRead
= fread (Buffer
, sizeof (UINT8
), FileSize
, Fp
);
1782 LocalVtfBuffer
= (UINT8
*) Vtf1EndBuffer
- SIZE_IA32_RESET_VECT
;
1783 memcpy (LocalVtfBuffer
, Buffer
, FileSize
);
1801 Routine Description:
1803 This function cleans up any allocated buffer
1815 PARSED_VTF_INFO
*TempFileListPtr
;
1826 // Cleanup the buffer which was allocated to read the file names from FV.INF
1828 FileListPtr
= FileListHeadPtr
;
1829 while (FileListPtr
!= NULL
) {
1830 TempFileListPtr
= FileListPtr
->NextVtfInfo
;
1832 FileListPtr
= TempFileListPtr
;
1837 ProcessAndCreateVtf (
1842 Routine Description:
1844 This function process the link list created during INF file parsing
1845 and create component in VTF and updates its info in FIT table
1849 Size - Size of the Firmware Volume of which, this VTF belongs to.
1853 EFI_UNSUPPORTED - Unknown FIT type
1854 EFI_SUCCESS - The function completed successfully
1859 PARSED_VTF_INFO
*ParsedInfoPtr
;
1861 Status
= EFI_SUCCESS
;
1863 ParsedInfoPtr
= FileListHeadPtr
;
1865 while (ParsedInfoPtr
!= NULL
) {
1867 switch (ParsedInfoPtr
->CompType
) {
1869 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1871 case COMP_TYPE_FIT_HEADER
:
1872 //COMP_TYPE_FIT_HEADER 0x00
1873 Status
= CreateFitTableAndInitialize (ParsedInfoPtr
);
1877 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1879 case COMP_TYPE_FIT_PAL_A
:
1880 //COMP_TYPE_FIT_PAL_A 0x0F
1881 Status
= CreateAndUpdatePAL_A (ParsedInfoPtr
);
1884 // Based on VTF specification, once the PAL_A component has been written,
1885 // update the Firmware Volume info as FIT table. This will be utilized
1886 // to extract the Firmware Volume Start address where this VTF will be
1889 if (Status
== EFI_SUCCESS
) {
1890 UpdateFitEntryForFwVolume (Size
);
1894 case COMP_TYPE_FIT_FV_BOOT
:
1895 //COMP_TYPE_FIT_FV_BOOT 0x7E
1897 // Since FIT entry for Firmware Volume has been created and it is
1898 // located at (PAL_A start - 16 byte). So we will not process any
1899 // Firmware Volume related entry from INF file
1901 Status
= EFI_SUCCESS
;
1906 // Any other component type should be handled here. This will create the
1907 // image in specified VTF and create appropriate entry about this
1908 // component in FIT Entry.
1910 Status
= CreateAndUpdateComponent (ParsedInfoPtr
);
1911 if (EFI_ERROR (Status
)) {
1912 Error (NULL
, 0, 0002, "Error updating component", ParsedInfoPtr
->CompName
);
1918 ParsedInfoPtr
= ParsedInfoPtr
->NextVtfInfo
;
1925 IN UINT64 StartAddress1
,
1927 IN UINT64 StartAddress2
,
1933 Routine Description:
1935 This is the main function which will be called from application.
1939 StartAddress1 - The start address of the first VTF
1940 Size1 - The size of the first VTF
1941 StartAddress2 - The start address of the second VTF
1942 Size2 - The size of the second VTF
1943 fp - The pointer to BSF inf file
1947 EFI_OUT_OF_RESOURCES - Can not allocate memory
1948 The return value can be any of the values
1949 returned by the calls to following functions:
1950 GetVtfRelatedInfoFromInfFile
1952 UpdateIA32ResetVector
1961 Status
= EFI_UNSUPPORTED
;
1964 if (StartAddress2
== 0) {
1970 Fv1BaseAddress
= StartAddress1
;
1971 Fv1EndAddress
= Fv1BaseAddress
+ Size1
;
1972 if (Fv1EndAddress
!= 0x100000000ULL
|| Size1
< 0x100000) {
1973 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1974 if (Size1
< 0x100000) {
1975 Error (NULL
, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
1976 } else if (SecondVTF
!= TRUE
) {
1977 Error (NULL
, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
1980 return EFI_INVALID_PARAMETER
;
1984 // The image buffer for the First VTF
1986 Vtf1Buffer
= malloc ((UINTN
) Size1
);
1987 if (Vtf1Buffer
== NULL
) {
1988 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
1989 return EFI_OUT_OF_RESOURCES
;
1991 memset (Vtf1Buffer
, 0x00, (UINTN
) Size1
);
1992 Vtf1EndBuffer
= (UINT8
*) Vtf1Buffer
+ Size1
;
1993 Vtf1LastStartAddress
= Fv1EndAddress
| IPF_CACHE_BIT
;
1996 Fv2BaseAddress
= StartAddress2
;
1997 Fv2EndAddress
= Fv2BaseAddress
+ Size2
;
1998 if (Fv2EndAddress
!= StartAddress1
) {
1999 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
2000 if (SecondVTF
== TRUE
) {
2001 Error (NULL
, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
2002 Error (NULL
, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
2005 return EFI_INVALID_PARAMETER
;
2009 // The image buffer for the second VTF
2011 Vtf2Buffer
= malloc ((UINTN
) Size2
);
2012 if (Vtf2Buffer
== NULL
) {
2013 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2014 return EFI_OUT_OF_RESOURCES
;
2016 memset (Vtf2Buffer
, 0x00, (UINTN
) Size2
);
2017 Vtf2EndBuffer
= (UINT8
*) Vtf2Buffer
+ Size2
;
2018 Vtf2LastStartAddress
= Fv2EndAddress
| IPF_CACHE_BIT
;
2021 Status
= GetVtfRelatedInfoFromInfFile (VtfFP
);
2023 if (Status
!= EFI_SUCCESS
) {
2024 Error (NULL
, 0, 0003, "Error parsing file", "the input file.");
2029 Status
= ProcessAndCreateVtf (Size1
);
2030 if (Status
!= EFI_SUCCESS
) {
2035 if (SectionOptionFlag
) {
2036 Status
= UpdateIA32ResetVector (IA32BinFile
, Vtf1TotalSize
);
2037 if (Status
!= EFI_SUCCESS
) {
2044 // Re arrange the FIT Table for Ascending order of their FIT Type..
2049 // All components have been updated in FIT table. Now perform the FIT table
2050 // checksum. The following function will check if Checksum is required,
2051 // if yes, then it will perform the checksum otherwise not.
2053 CalculateFitTableChecksum ();
2056 // Write the FFS header
2058 Vtf1TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2059 Vtf1LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2061 Status
= UpdateFfsHeader (Vtf1TotalSize
, FIRST_VTF
);
2062 if (Status
!= EFI_SUCCESS
) {
2067 // Update the VTF buffer into specified VTF binary file
2069 Status
= WriteVtfBinary (OutFileName1
, Vtf1TotalSize
, FIRST_VTF
);
2072 Vtf2TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2073 Vtf2LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2074 Status
= UpdateFfsHeader (Vtf2TotalSize
, SECOND_VTF
);
2075 if (Status
!= EFI_SUCCESS
) {
2081 // Update the VTF buffer into specified VTF binary file
2083 Status
= WriteVtfBinary (OutFileName2
, Vtf2TotalSize
, SECOND_VTF
);
2092 PeimFixupInFitTable (
2093 IN UINT64 StartAddress
2097 Routine Description:
2099 This function is an entry point to fixup SAL-E entry point.
2103 StartAddress - StartAddress for PEIM.....
2107 EFI_SUCCESS - The function completed successfully
2108 EFI_ABORTED - Error Opening File
2109 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2115 UINT64
*StartAddressPtr
;
2119 StartAddressPtr
= malloc (sizeof (UINT64
));
2120 if (StartAddressPtr
== NULL
) {
2121 return EFI_OUT_OF_RESOURCES
;
2123 *StartAddressPtr
= StartAddress
;
2125 Fp
= fopen (OutFileName1
, "rb");
2128 Error (NULL
, 0, 0001, "Error opening file", OutFileName1
);
2129 if (StartAddressPtr
) {
2130 free (StartAddressPtr
);
2135 FirstFwVSize
= _filelength (fileno (Fp
));
2136 fseek (Fp
, (long) (FirstFwVSize
- (UINTN
) (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
)), SEEK_SET
);
2137 NumByte
= fwrite ((VOID
*) StartAddressPtr
, sizeof (UINT64
), 1, Fp
);
2143 if (StartAddressPtr
) {
2144 free (StartAddressPtr
);
2147 Status
= EFI_SUCCESS
;
2153 IN UINT64 BaseAddress
,
2154 IN CHAR8
*DestFileName
,
2155 IN CHAR8
*SourceFileName
,
2161 Routine Description:
2163 This function adds the SYM tokens in the source file to the destination file.
2164 The SYM tokens are updated to reflect the base address.
2168 BaseAddress - The base address for the new SYM tokens.
2169 DestFileName - The destination file.
2170 SourceFileName - The source file.
2171 FileSize - Size of bin file.
2175 EFI_SUCCESS - The function completed successfully.
2176 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2177 EFI_ABORTED - An error occurred.
2183 CHAR8 Buffer
[_MAX_PATH
];
2184 CHAR8 Type
[_MAX_PATH
];
2185 CHAR8 Address
[_MAX_PATH
];
2186 CHAR8 Section
[_MAX_PATH
];
2187 CHAR8 Token
[_MAX_PATH
];
2188 CHAR8 BaseToken
[_MAX_PATH
];
2189 UINT64 TokenAddress
;
2193 // Verify input parameters.
2195 if (BaseAddress
== 0 || DestFileName
== NULL
|| SourceFileName
== NULL
) {
2196 return EFI_INVALID_PARAMETER
;
2200 // Open the source file
2202 SourceFile
= fopen (SourceFileName
, "r");
2203 if (SourceFile
== NULL
) {
2206 // SYM files are not required.
2212 // Use the file name minus extension as the base for tokens
2214 strcpy (BaseToken
, SourceFileName
);
2215 strtok (BaseToken
, ". \t\n");
2216 strcat (BaseToken
, "__");
2219 // Open the destination file
2221 DestFile
= fopen (DestFileName
, "a+");
2222 if (DestFile
== NULL
) {
2223 fclose (SourceFile
);
2224 Error (NULL
, 0, 0001, "Error opening file", DestFileName
);
2229 // If this is the beginning of the output file, write the symbol format info.
2231 if (fseek (DestFile
, 0, SEEK_END
) != 0) {
2232 fclose (SourceFile
);
2234 Error (NULL
, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2238 StartLocation
= ftell (DestFile
);
2240 if (StartLocation
== 0) {
2241 fprintf (DestFile
, "TEXTSYM format | V1.0\n");
2242 } else if (StartLocation
== -1) {
2243 fclose (SourceFile
);
2245 Error (NULL
, 0, 2000, "Invalid parameter", "StartLocation error");
2250 // Read the first line
2252 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
2257 // Make sure it matches the expected sym format
2259 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
2260 fclose (SourceFile
);
2262 Error (NULL
, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2269 while (feof (SourceFile
) == 0) {
2274 if (fscanf (SourceFile
, "%s | %s | %s | %s\n", Type
, Address
, Section
, Token
) == 4) {
2277 // Get the token address
2279 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
2280 if (TokenAddress
> FileSize
) {
2282 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2288 // Add the base address, the size of the FFS file header and the size of the peim header.
2290 TokenAddress
+= BaseAddress
&~IPF_CACHE_BIT
;
2292 fprintf (DestFile
, "%s | %016llX | ", Type
, (unsigned long long) TokenAddress
);
2293 fprintf (DestFile
, "%s | %s\n %s\n", Section
, Token
, BaseToken
);
2297 fclose (SourceFile
);
2303 CalculateFitTableChecksum (
2308 Routine Description:
2310 This function will perform byte checksum on the FIT table, if the the checksum required
2311 field is set to CheckSum required. If the checksum is not required then checksum byte
2312 will have value as 0;.
2320 Status - Value returned by call to CalculateChecksum8 ()
2321 EFI_SUCCESS - The function completed successfully
2325 FIT_TABLE
*TmpFitPtr
;
2327 UINT64 FitTableAddOffset
;
2328 UINTN RelativeAddress
;
2332 // Read the Fit Table address from Itanium-based address map.
2334 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
2337 // Translate this Itanium-based address in terms of local buffer address which
2338 // contains the image for Boot Strapped File
2340 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
2341 FitTableAdd
= *(UINTN
*) RelativeAddress
;
2343 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
2345 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
2347 Size
= TmpFitPtr
->CompSize
* 16;
2349 if ((TmpFitPtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2350 TmpFitPtr
->CheckSum
= 0;
2351 TmpFitPtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) TmpFitPtr
, Size
);
2353 TmpFitPtr
->CheckSum
= 0;
2365 Routine Description:
2367 Displays the standard utility information to SDTOUT
2379 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
2388 Routine Description:
2390 Displays the utility usage syntax to STDOUT
2405 fprintf (stdout
, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME
);
2408 // Copyright declaration
2410 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
2414 fprintf (stdout
, "Options:\n");
2415 fprintf (stdout
, " -f Input_file, --filename Input_file\n\
2416 Input_file is name of the BS Image INF file\n");
2417 fprintf (stdout
, " -r BaseAddress, --baseaddr BaseAddress\n\
2418 BaseAddress is the starting address of Firmware Volume\n\
2419 where Boot Strapped Image will reside.\n");
2420 fprintf (stdout
, " -s FwVolumeSize, --size FwVolumeSize\n\
2421 FwVolumeSize is the size of Firmware Volume.\n");
2422 fprintf (stdout
, " -o FileName, --output FileName\n\
2423 File will be created to store the ouput content.\n");
2424 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
2425 fprintf (stdout
, " --version Show program's version number and exit.\n");
2426 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
2427 fprintf (stdout
, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
2428 fprintf (stdout
, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
2438 Routine Description:
2440 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2441 part of firmware volume image.
2445 argc - The count of the parameters
2446 argv - The parameters
2451 0 - No error conditions detected.
2452 1 - One or more of the input parameters is invalid.
2453 2 - A resource required by the utility was unavailable.
2454 - Most commonly this will be memory allocation or file creation.
2455 3 - GenFvImage.dll could not be loaded.
2456 4 - Error executing the GenFvImage dll.
2457 5 - Now this tool does not support the IA32 platform
2462 UINT64 StartAddress1
;
2463 UINT64 StartAddress2
;
2466 BOOLEAN FirstRoundO
;
2467 BOOLEAN FirstRoundB
;
2468 BOOLEAN FirstRoundS
;
2473 SetUtilityName (UTILITY_NAME
);
2476 // Initialize variables
2486 OutFileName1
= NULL
;
2487 OutFileName2
= NULL
;
2492 // Verify the correct number of arguments
2499 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
2504 if ((strcmp(argv
[1], "--version") == 0)) {
2510 // Parse the command line arguments
2512 for (Index
= 1; Index
< argc
; Index
+= 2) {
2513 if ((stricmp (argv
[Index
], "-o") == 0) || (stricmp (argv
[Index
], "--output") == 0)) {
2514 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2515 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
2519 // Get the output file name
2524 // It's the first output file name
2526 OutFileName1
= (CHAR8
*)argv
[Index
+1];
2527 FirstRoundO
= FALSE
;
2530 //It's the second output file name
2532 OutFileName2
= (CHAR8
*)argv
[Index
+1];
2537 if ((stricmp (argv
[Index
], "-f") == 0) || (stricmp (argv
[Index
], "--filename") == 0)) {
2538 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2539 Error (NULL
, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
2543 // Get the input VTF file name
2545 VtfFileName
= argv
[Index
+1];
2546 VtfFP
= fopen(VtfFileName
, "rb");
2547 if (VtfFP
== NULL
) {
2548 Error (NULL
, 0, 0001, "Error opening file", VtfFileName
);
2554 if ((stricmp (argv
[Index
], "-r") == 0) || (stricmp (argv
[Index
], "--baseaddr") == 0)) {
2556 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress1
);
2557 FirstRoundB
= FALSE
;
2559 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress2
);
2561 if (Status
!= EFI_SUCCESS
) {
2562 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv
[Index
+ 1]);
2568 if ((stricmp (argv
[Index
], "-s") == 0) || (stricmp (argv
[Index
], "--size") == 0)) {
2570 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize1
);
2571 FirstRoundS
= FALSE
;
2573 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize2
);
2577 if (Status
!= EFI_SUCCESS
) {
2578 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv
[Index
+ 1]);
2584 if ((stricmp (argv
[Index
], "-v") == 0) || (stricmp (argv
[Index
], "--verbose") == 0)) {
2590 if ((stricmp (argv
[Index
], "-q") == 0) || (stricmp (argv
[Index
], "--quiet") == 0)) {
2596 if ((stricmp (argv
[Index
], "-d") == 0) || (stricmp (argv
[Index
], "--debug") == 0)) {
2598 // debug level specified
2600 Status
= AsciiStringToUint64(argv
[Index
+ 1], FALSE
, &DebugLevel
);
2601 if (EFI_ERROR (Status
)) {
2602 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[Index
], argv
[Index
+ 1]);
2605 if (DebugLevel
> 9) {
2606 Error (NULL
, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv
[Index
+ 1]);
2609 if((DebugLevel
<= 9) &&(DebugLevel
>= 5)) {
2617 Error (NULL
, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv
[Index
]);
2621 if (VtfFP
== NULL
) {
2622 Error (NULL
, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2627 Error (NULL
, 0, 2000, "Invalid parameter", "No FV base address is specified");
2632 Error (NULL
, 0, 2000, "Invalid parameter", "No FV Size is specified");
2636 // All Parameters has been parsed, now set the message print level
2640 } else if (VerboseMode
) {
2642 } else if (DebugMode
) {
2643 SetPrintLevel(DebugLevel
);
2647 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
2650 if (VTF_OUTPUT
== FALSE
) {
2651 if (SecondVTF
== TRUE
) {
2652 OutFileName1
= VTF_OUTPUT_FILE1
;
2653 OutFileName2
= VTF_OUTPUT_FILE2
;
2655 OutFileName1
= VTF_OUTPUT_FILE1
;
2657 SymFileName
= VTF_SYM_FILE
;
2659 INTN OutFileNameLen
= strlen(OutFileName1
);
2662 for (Index
= OutFileNameLen
; Index
> 0; --Index
) {
2663 if (OutFileName1
[Index
] == '/' || OutFileName1
[Index
] == '\\') {
2668 SymFileName
= VTF_SYM_FILE
;
2670 INTN SymFileNameLen
= Index
+ 1 + strlen(VTF_SYM_FILE
);
2671 SymFileName
= malloc(SymFileNameLen
+ 1);
2672 memcpy(SymFileName
, OutFileName1
, Index
+ 1);
2673 memcpy(SymFileName
+ Index
+ 1, VTF_SYM_FILE
, strlen(VTF_SYM_FILE
));
2674 SymFileName
[SymFileNameLen
] = '\0';
2677 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, SymFileName
, NULL
);
2682 // Call the GenVtfImage
2685 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Start to generate the VTF image\n", NULL
);
2687 Status
= GenerateVtfImage (StartAddress1
, FwVolSize1
, StartAddress2
, FwVolSize2
, VtfFP
);
2689 if (EFI_ERROR (Status
)) {
2692 case EFI_INVALID_PARAMETER
:
2693 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2697 Error (NULL
, 0, 3000, "Invalid", "Error detected while creating the file image.");
2700 case EFI_OUT_OF_RESOURCES
:
2701 Error (NULL
, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2704 case EFI_VOLUME_CORRUPTED
:
2705 Error (NULL
, 0, 3000, "Invalid", "No base address was specified.");
2709 Error (NULL
, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status
);
2714 if (VtfFP
!= NULL
) {
2719 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "VTF image generated successful\n", NULL
);
2723 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2725 return GetUtilityStatus();