2 This file contains functions required to generate a boot strap file (BSF) also
3 known as the Volume Top File (VTF)
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
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.
20 #include <Common/UefiBaseTypes.h>
22 #include <Guid/PiFirmwareFileSystem.h>
23 #include "CommonLib.h"
24 #include "EfiUtilityMsgs.h"
29 UINTN SectionOptionFlag
= 0;
30 UINTN SectionCompFlag
= 0;
35 BOOLEAN QuietMode
= FALSE
;
37 BOOLEAN VTF_OUTPUT
= FALSE
;
45 PARSED_VTF_INFO
*FileListPtr
;
46 PARSED_VTF_INFO
*FileListHeadPtr
;
53 UINTN ValidLineNum
= 0;
54 UINTN ValidFFDFileListNum
= 0;
57 // Section Description and their number of occurences in *.INF file
60 UINTN SectionOptionNum
= 0;
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
66 BOOLEAN VTFPresent
= FALSE
;
67 BOOLEAN SecondVTF
= FALSE
;
70 // Address related information
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;
81 UINT32 BufferToTop
= 0;
84 // IA32 Reset Vector Bin name
86 CHAR8 IA32BinFile
[FILE_NAME_SIZE
];
89 // Function Implementations
94 IN OUT UINT8
*MajorVer
,
95 IN OUT UINT8
*MinorVer
100 This function split version to major version and minor version
104 Str - String representing in form XX.XX
105 MajorVer - The major version
106 MinorVer - The minor version
110 EFI_SUCCESS - The function completed successfully.
114 CHAR8 TemStr
[5] = "0000";
122 if (strstr (Str
, ".") != NULL
) {
130 Length
= strlen(Str
);
132 strncpy (TemStr
+ 4 - Length
, Str
, Length
);
134 strncpy (TemStr
, Str
+ Length
- 4, 4);
145 *MajorVer
= (UINT8
) Major
;
146 *MinorVer
= (UINT8
) Minor
;
157 This function cleans up the line by removing all whitespace and
162 Line - The pointer of the string
170 CHAR8 TmpLine
[FILE_NAME_SIZE
];
177 // Change '#' to '//' for Comment style
179 if (((Ptr0
= strchr (Line
, '#')) != NULL
) || ((Ptr0
= strstr (Line
, "//")) != NULL
)) {
180 Line
[Ptr0
- Line
] = 0;
184 // Initialize counters
189 while ((Char
= Line
[Index
]) != 0) {
190 if ((Char
!= ' ') && (Char
!= '\t') && (Char
!= '\n') && (Char
!= '\r')) {
191 TmpLine
[Index2
++] = Char
;
197 strcpy (Line
, TmpLine
);
208 This function calculated number of valid lines in a input file.
212 Fp - Pointer to a file handle which has been opened.
220 CHAR8 Buff
[FILE_NAME_SIZE
];
221 while (fgets(Buff
, sizeof (Buff
), Fp
)) {
238 This function parses the input file and tokenize the string
242 Fp - Pointer to a file handle which has been opened.
251 CHAR8 Buff
[FILE_NAME_SIZE
+ 1];
252 CHAR8 Delimit
[] = "=";
254 Buff
[FILE_NAME_SIZE
] = '\0';
257 while (fgets (Buff
, FILE_NAME_SIZE
, Fp
) != NULL
) {
262 Token
= strtok (Buff
, Delimit
);
263 while (Token
!= NULL
) {
264 strcpy (*TokenStr
, Token
);
266 Token
= strtok (NULL
, Delimit
);
280 This function initializes the relevant global variable which is being
281 used to store the information retrieved from INF file. This also initializes
290 EFI_SUCCESS - The function completed successfully
291 EFI_OUT_OF_RESOURCES - Malloc failed.
296 FileListPtr
= malloc (sizeof (PARSED_VTF_INFO
));
298 if (FileListPtr
== NULL
) {
299 return EFI_OUT_OF_RESOURCES
;
302 FileListHeadPtr
= FileListPtr
;
303 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
304 FileListPtr
->NextVtfInfo
= NULL
;
306 remove (SymFileName
);
311 ParseAndUpdateComponents (
312 IN PARSED_VTF_INFO
*VtfInfo
318 This function initializes the relevant global variable which is being
319 used to store the information retrieved from INF file.
323 VtfInfo - A pointer to the VTF Info Structure
334 while (*TokenStr
!= NULL
&& (strnicmp (*TokenStr
, "COMP_NAME", 9) != 0)) {
336 if (strnicmp (*TokenStr
, "COMP_LOC", 8) == 0) {
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
;
343 VtfInfo
->LocationType
= NONE
;
345 } else if (strnicmp (*TokenStr
, "COMP_TYPE", 9) == 0) {
347 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
348 Error (NULL
, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr
);
352 VtfInfo
->CompType
= (UINT8
) StringValue
;
353 } else if (strnicmp (*TokenStr
, "COMP_VER", 8) == 0) {
355 if (strnicmp (*TokenStr
, "-", 1) == 0) {
356 VtfInfo
->VersionPresent
= FALSE
;
357 VtfInfo
->MajorVer
= 0;
358 VtfInfo
->MinorVer
= 0;
360 VtfInfo
->VersionPresent
= TRUE
;
361 ConvertVersionInfo (*TokenStr
, &VtfInfo
->MajorVer
, &VtfInfo
->MinorVer
);
363 } else if (strnicmp (*TokenStr
, "COMP_BIN", 8) == 0) {
365 strcpy (VtfInfo
->CompBinName
, *TokenStr
);
366 } else if (strnicmp (*TokenStr
, "COMP_SYM", 8) == 0) {
368 strcpy (VtfInfo
->CompSymName
, *TokenStr
);
369 } else if (strnicmp (*TokenStr
, "COMP_SIZE", 9) == 0) {
371 if (strnicmp (*TokenStr
, "-", 1) == 0) {
372 VtfInfo
->PreferredSize
= FALSE
;
373 VtfInfo
->CompSize
= 0;
375 VtfInfo
->PreferredSize
= TRUE
;
376 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
377 Error (NULL
, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr
);
381 VtfInfo
->CompSize
= (UINTN
) StringValue
;
384 } else if (strnicmp (*TokenStr
, "COMP_CS", 7) == 0) {
386 if (strnicmp (*TokenStr
, "1", 1) == 0) {
387 VtfInfo
->CheckSumRequired
= 1;
388 } else if (strnicmp (*TokenStr
, "0", 1) == 0) {
389 VtfInfo
->CheckSumRequired
= 0;
391 Error (NULL
, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
396 if (*TokenStr
== NULL
) {
403 InitializeInFileInfo (
410 This function intializes the relevant global variable which is being
411 used to store the information retrieved from INF file.
424 SectionOptionFlag
= 0;
426 TokenStr
= OrgStrTokPtr
;
428 while (*TokenStr
!= NULL
) {
429 if (strnicmp (*TokenStr
, "[OPTIONS]", 9) == 0) {
430 SectionOptionFlag
= 1;
434 if (strnicmp (*TokenStr
, "[COMPONENTS]", 12) == 0) {
435 if (FileListPtr
== NULL
) {
436 FileListPtr
= FileListHeadPtr
;
440 SectionOptionFlag
= 0;
444 if (SectionOptionFlag
) {
445 if (stricmp (*TokenStr
, "IA32_RST_BIN") == 0) {
447 strcpy (IA32BinFile
, *TokenStr
);
451 if (SectionCompFlag
) {
452 if (stricmp (*TokenStr
, "COMP_NAME") == 0) {
454 strcpy (FileListPtr
->CompName
, *TokenStr
);
456 ParseAndUpdateComponents (FileListPtr
);
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
);
465 FileListPtr
= FileListPtr
->NextVtfInfo
;
466 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
467 FileListPtr
->NextVtfInfo
= NULL
;
479 GetVtfRelatedInfoFromInfFile (
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
491 FileName - FileName which needed to be read to parse data
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
507 Status
= EFI_SUCCESS
;
510 Error (NULL
, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
516 if (ValidLineNum
== 0) {
517 Error (NULL
, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
518 return EFI_INVALID_PARAMETER
;
521 TokenStr
= (CHAR8
**) malloc (sizeof (UINTN
) * (2 * ValidLineNum
+ 1));
523 if (TokenStr
== NULL
) {
524 return EFI_OUT_OF_RESOURCES
;
527 memset (TokenStr
, 0, (sizeof (UINTN
) * (2 * ValidLineNum
+ 1)));
528 OrgStrTokPtr
= TokenStr
;
530 for (Index
= 0; Index
< (2 * ValidLineNum
); Index
++) {
531 *TokenStr
= (CHAR8
*)malloc (sizeof (CHAR8
) * FILE_NAME_SIZE
);
533 if (*TokenStr
== NULL
) {
534 Status
= EFI_OUT_OF_RESOURCES
;
538 memset (*TokenStr
, 0, FILE_NAME_SIZE
);
542 TokenStr
= OrgStrTokPtr
;
543 fseek (Fp
, 0L, SEEK_SET
);
545 Status
= InitializeComps ();
547 if (Status
!= EFI_SUCCESS
) {
551 Status
= ParseInputFile (Fp
);
552 if (Status
!= EFI_SUCCESS
) {
556 InitializeInFileInfo ();
560 for (Index1
= 0; Index1
< Index
; Index1
++) {
561 free (OrgStrTokPtr
[Index1
]);
570 GetRelativeAddressInVtfBuffer (
572 IN OUT UINTN
*RelativeAddress
,
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.
586 Address - The address of the flash map space
587 RelativeAddress - The relative address of the Buffer
588 LocType - The type of the VTF
599 if (LocType
== FIRST_VTF
) {
600 LocalBuff
= (UINT8
*) Vtf1EndBuffer
;
601 TempAddress
= Fv1EndAddress
- Address
;
602 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
604 LocalBuff
= (UINT8
*) Vtf2EndBuffer
;
605 TempAddress
= Fv2EndAddress
- Address
;
606 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
611 GetComponentVersionInfo (
612 IN OUT PARSED_VTF_INFO
*VtfInfo
,
618 This function will extract the version information from File
622 VtfInfo - A Pointer to the VTF Info Structure
623 Buffer - A Pointer to type UINT8
627 EFI_SUCCESS - The function completed successfully
628 EFI_INVALID_PARAMETER - The parameter is invalid
635 switch (VtfInfo
->CompType
) {
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
;
646 Status
= EFI_INVALID_PARAMETER
;
654 CheckAddressAlignment (
656 IN UINT64 AlignmentData
,
657 IN OUT UINT64
*AlignAdjustByte
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.
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.
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.
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
687 *AlignAdjustByte
= (Address
% AlignmentData
);
689 if (*AlignAdjustByte
== 0) {
697 GetFitTableStartAddress (
698 IN OUT FIT_TABLE
**FitTable
704 Get the FIT table start address in VTF Buffer
708 FitTable - Pointer to available fit table where new component can be added
712 EFI_SUCCESS - The function completed successfully
717 UINT64 FitTableAddOffset
;
718 UINTN RelativeAddress
;
721 // Read the Fit Table address from Itanium-based address map.
723 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
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.
730 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
731 FitTableAdd
= *(UINTN
*) RelativeAddress
;
734 // The FitTableAdd is the extracted Itanium based address pointing to FIT
735 // table. The relative address will return its actual location in VTF
738 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
740 *FitTable
= (FIT_TABLE
*) RelativeAddress
;
746 GetNextAvailableFitPtr (
747 IN FIT_TABLE
**FitPtr
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.
762 FitPtr - Pointer to available fit table where new component can be added
766 EFI_SUCCESS - The function completed successfully
770 FIT_TABLE
*TmpFitPtr
;
772 UINT64 FitTableAddOffset
;
774 UINTN NumFitComponents
;
775 UINTN RelativeAddress
;
778 // Read the Fit Table address from Itanium-based address map.
780 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
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.
787 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
788 FitTableAdd
= *(UINTN
*) RelativeAddress
;
791 // The FitTableAdd is the extracted Itanium based address pointing to FIT
792 // table. The relative address will return its actual location in VTF
795 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
797 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
798 NumFitComponents
= TmpFitPtr
->CompSize
;
800 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
801 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_UNUSED
) {
821 This function is used by qsort to sort the FIT table based upon Component
822 Type in their incresing order.
826 Arg1 - Pointer to Arg1
827 Arg2 - Pointer to Arg2
835 if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) > (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
837 } else if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) < (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
852 This function is used by qsort to sort the FIT table based upon Component
853 Type in their incresing order.
866 FIT_TABLE
*TmpFitPtr
;
867 UINTN NumFitComponents
;
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;
879 qsort ((VOID
*) FitTable
, NumFitComponents
, sizeof (FIT_TABLE
), CompareItems
);
883 UpdateFitEntryForFwVolume (
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..
898 Size - Firmware Volume Size
906 FIT_TABLE
*CompFitPtr
;
907 UINTN RelativeAddress
;
910 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
912 Vtf1LastStartAddress
-= 0x10;
913 Vtf1TotalSize
+= 0x10;
915 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
917 CompFitPtr
= (FIT_TABLE
*) RelativeAddress
;
918 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
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
927 // Firmware Volume Size in 16 byte block
929 CompFitPtr
->CompSize
= ((UINT32
) Size
) / 16;
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.
936 CompFitPtr
->CompVersion
= MAKE_VERSION (0, 0);
939 // Since we don't have any info about this file, we are making sure that
940 // checksum is not needed.
942 CompFitPtr
->CvAndType
= CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT
);
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
951 CompFitPtr
->CheckSum
= 0;
955 UpdateFitEntryForNonVTFComp (
956 IN PARSED_VTF_INFO
*VtfInfo
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
969 VtfInfo - Pointer to VTF Info Structure
973 EFI_ABORTED - The function fails to update the component in FIT
974 EFI_SUCCESS - The function completed successfully
978 FIT_TABLE
*CompFitPtr
;
981 // Scan the FIT table for available space
983 GetNextAvailableFitPtr (&CompFitPtr
);
984 if (CompFitPtr
== NULL
) {
985 Error (NULL
, 0, 5003, "Invalid", "Can't update this component in FIT");
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
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
);
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
1006 CompFitPtr
->CheckSum
= 0;
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.
1012 if ((CompFitPtr
->CvAndType
& 0x7F) == COMP_TYPE_FIT_FV_BOOT
) {
1013 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
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
1030 IN PARSED_VTF_INFO
*VtfInfo
,
1031 IN UINT64
*CompStartAddress
1035 Routine Description:
1037 This function updated the architectural entry point in IPF, SALE_ENTRY.
1041 VtfInfo - Pointer to VTF Info Structure
1042 CompStartAddress - Pointer to Component Start Address
1046 EFI_INVALID_PARAMETER - The parameter is invalid
1047 EFI_SUCCESS - The function completed successfully
1051 UINTN RelativeAddress
;
1056 CHAR8 Buff
[FILE_NAME_SIZE
];
1059 CHAR8 OffsetStr
[30];
1065 Fp
= fopen (LongFilePath (VtfInfo
->CompSymName
), "rb");
1068 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompSymName
);
1069 return EFI_INVALID_PARAMETER
;
1072 while (fgets (Buff
, sizeof (Buff
), Fp
) != NULL
) {
1075 "%s %s %s %s %s %s %s",
1084 if (strnicmp (Token
, "SALE_ENTRY", 10) == 0) {
1089 Offset
= strtoul (OffsetStr
, NULL
, 16);
1091 *CompStartAddress
+= Offset
;
1092 SalEntryAdd
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
);
1094 GetRelativeAddressInVtfBuffer (SalEntryAdd
, &RelativeAddress
, FIRST_VTF
);
1096 memcpy ((VOID
*) RelativeAddress
, (VOID
*) CompStartAddress
, sizeof (UINT64
));
1106 CreateAndUpdateComponent (
1107 IN PARSED_VTF_INFO
*VtfInfo
1111 Routine Description:
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
1119 VtfInfo - Pointer to Parsed Info
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.
1128 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1129 EFI_OUT_OF_RESOURCES Memory allocation failure.
1134 UINT64 CompStartAddress
;
1136 UINT64 NumAdjustByte
;
1139 FIT_TABLE
*CompFitPtr
;
1142 if (VtfInfo
->LocationType
== NONE
) {
1143 UpdateFitEntryForNonVTFComp (VtfInfo
);
1147 Fp
= fopen (LongFilePath (VtfInfo
->CompBinName
), "rb");
1150 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1154 FileSize
= _filelength (fileno (Fp
));
1155 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1158 // BUGBUG: Satish to correct
1160 FileSize
-= SIZE_OF_PAL_HEADER
;
1163 if (VtfInfo
->PreferredSize
) {
1164 if (FileSize
> VtfInfo
->CompSize
) {
1165 Error (NULL
, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1169 FileSize
= VtfInfo
->CompSize
;
1172 Buffer
= malloc ((UINTN
) FileSize
);
1173 if (Buffer
== NULL
) {
1174 return EFI_OUT_OF_RESOURCES
;
1176 memset (Buffer
, 0, (UINTN
) FileSize
);
1178 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1181 // Read first 64 bytes of PAL header and use it to find version info
1183 fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1186 // PAL header contains the version info. Currently, we will use the header
1187 // to read version info and then discard.
1189 if (!VtfInfo
->VersionPresent
) {
1190 GetComponentVersionInfo (VtfInfo
, Buffer
);
1194 fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
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.
1201 if (VtfInfo
->CompType
!= COMP_TYPE_FIT_PAL_B
) {
1202 if (!VtfInfo
->VersionPresent
) {
1203 GetComponentVersionInfo (VtfInfo
, Buffer
);
1207 if (VtfInfo
->LocationType
== SECOND_VTF
) {
1209 CompStartAddress
= (Vtf2LastStartAddress
- FileSize
);
1211 CompStartAddress
= (Vtf1LastStartAddress
- FileSize
);
1214 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) {
1215 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 32 * 1024, &NumAdjustByte
);
1217 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 8, &NumAdjustByte
);
1221 CompStartAddress
-= NumAdjustByte
;
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
);
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
;
1237 if (EFI_ERROR (Status
)) {
1241 GetNextAvailableFitPtr (&CompFitPtr
);
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
;
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
);
1265 // Update the SYM file for this component based on it's start address.
1267 Status
= UpdateSymFile (CompStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1268 if (EFI_ERROR (Status
)) {
1271 // At this time, SYM files are not required, so continue on error.
1275 // !!!!!!!!!!!!!!!!!!!!!
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 // !!!!!!!!!!!!!!!!!!!!!!!
1282 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PEICORE
) {
1283 Status
= UpdateEntryPoint (VtfInfo
, &CompStartAddress
);
1290 CreateAndUpdatePAL_A (
1291 IN PARSED_VTF_INFO
*VtfInfo
1295 Routine Description:
1297 This function reads the binary file for each components and update them
1298 in VTF Buffer as well as FIT table
1302 VtfInfo - Pointer to Parsed Info
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.
1319 UINT64 PalStartAddress
;
1321 UINTN RelativeAddress
;
1325 FIT_TABLE
*PalFitPtr
;
1327 Fp
= fopen (LongFilePath (VtfInfo
->CompBinName
), "rb");
1330 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
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
;
1339 FileSize
-= SIZE_OF_PAL_HEADER
;
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.");
1348 FileSize
= VtfInfo
->CompSize
;
1351 Buffer
= malloc ((UINTN
) FileSize
);
1352 if (Buffer
== NULL
) {
1353 return EFI_OUT_OF_RESOURCES
;
1355 memset (Buffer
, 0, (UINTN
) FileSize
);
1358 // Read, Get version Info and discard the PAL header.
1360 fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1363 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1365 if (!VtfInfo
->VersionPresent
) {
1366 GetComponentVersionInfo (VtfInfo
, Buffer
);
1370 // Read PAL_A file in a buffer
1372 fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
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
);
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
;
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
);
1403 // Update the SYM file for this component based on it's start address.
1405 Status
= UpdateSymFile (PalStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1406 if (EFI_ERROR (Status
)) {
1409 // At this time, SYM files are not required, so continue on error.
1417 CreateFitTableAndInitialize (
1418 IN PARSED_VTF_INFO
*VtfInfo
1422 Routine Description:
1424 This function creates and intializes FIT table which would be used to
1425 add component info inside this
1429 VtfInfo - Pointer to Parsed Info
1433 EFI_ABORTED - Aborted due to no size information
1434 EFI_SUCCESS - The function completed successfully
1438 UINT64 PalFitTableAdd
;
1440 UINT64 FitTableAddressOffset
;
1441 FIT_TABLE
*PalFitPtr
;
1442 FIT_TABLE
*FitStartPtr
;
1444 UINTN RelativeAddress
;
1447 if (!VtfInfo
->PreferredSize
) {
1448 Error (NULL
, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
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.");
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
);
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
;
1466 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1469 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1471 FitStartPtr
= (FIT_TABLE
*) RelativeAddress
;
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
);
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
1484 FitStartPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1486 NumFitComp
= FitStartPtr
->CompSize
;
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.
1495 for (Index
= 0; Index
< (NumFitComp
- 1); Index
++) {
1496 FitStartPtr
->CvAndType
= 0x7F; // Initialize all with UNUSED
1500 Vtf1TotalSize
+= VtfInfo
->CompSize
;
1501 Vtf1LastStartAddress
-= VtfInfo
->CompSize
;
1514 Routine Description:
1516 Write Firmware Volume from memory to a file.
1520 FileName - Output File Name which needed to be created/
1522 LocType - The type of the VTF
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
1536 UINTN RelativeAddress
;
1538 if (LocType
== FIRST_VTF
) {
1539 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1540 VtfBuffer
= (VOID
*) RelativeAddress
;
1542 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1543 VtfBuffer
= (VOID
*) RelativeAddress
;
1546 Fp
= fopen (LongFilePath (FileName
), "wb");
1548 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1552 NumByte
= fwrite (VtfBuffer
, sizeof (UINT8
), (UINTN
) VtfSize
, Fp
);
1558 if (NumByte
!= (sizeof (UINT8
) * VtfSize
)) {
1559 Error (NULL
, 0, 0002, "Error writing file", FileName
);
1568 IN UINT64 StartAddress
,
1575 Routine Description:
1577 Update the Firmware Volume Buffer with requested buffer data
1581 StartAddress - StartAddress in buffer. This number will automatically
1582 point to right address in buffer where data needed
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
1590 EFI_ABORTED - The input parameter is error
1591 EFI_SUCCESS - The function completed successfully
1595 UINT8
*LocalBufferPtrToWrite
;
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.");
1603 LocalBufferPtrToWrite
= (UINT8
*) Vtf1EndBuffer
;
1605 LocalBufferPtrToWrite
-= (Fv1EndAddress
- StartAddress
);
1609 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf2LastStartAddress
| IPF_CACHE_BIT
)) {
1610 Error (NULL
, 0, 2000, "Invalid parameter", "Error StartAddress");
1613 LocalBufferPtrToWrite
= (UINT8
*) Vtf2EndBuffer
;
1614 LocalBufferPtrToWrite
-= (Fv2EndAddress
- StartAddress
);
1617 memcpy (LocalBufferPtrToWrite
, Buffer
, (UINTN
) DataSize
);
1624 IN UINT32 TotalVtfSize
,
1629 Routine Description:
1631 Update the Firmware Volume Buffer with requested buffer data
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
1641 EFI_SUCCESS - The function completed successfully
1642 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1646 EFI_FFS_FILE_HEADER
*FileHeader
;
1647 UINTN RelativeAddress
;
1648 EFI_GUID EfiFirmwareVolumeTopFileGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1651 // Find the VTF file header location
1653 if (LocType
== FIRST_VTF
) {
1654 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1655 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1657 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1658 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1661 if (FileHeader
== NULL
) {
1662 return EFI_INVALID_PARAMETER
;
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
;
1674 // Now FileSize includes the EFI_FFS_FILE_HEADER
1676 FileHeader
->Size
[0] = (UINT8
) (TotalVtfSize
& 0x000000FF);
1677 FileHeader
->Size
[1] = (UINT8
) ((TotalVtfSize
& 0x0000FF00) >> 8);
1678 FileHeader
->Size
[2] = (UINT8
) ((TotalVtfSize
& 0x00FF0000) >> 16);
1681 // Fill in checksums and state, all three must be zero for the checksums.
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
;
1694 ValidateAddressAndSize (
1695 IN UINT64 BaseAddress
,
1700 Routine Description:
1702 Update the Firmware Volume Buffer with requested buffer data
1706 BaseAddress - Base address for the Fw Volume.
1708 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1712 EFI_SUCCESS - The function completed successfully
1713 EFI_UNSUPPORTED - The input parameter is error
1717 if ((FwVolSize
> 0x40) && ((BaseAddress
+ FwVolSize
) % 8 == 0)) {
1721 return EFI_UNSUPPORTED
;
1725 UpdateIA32ResetVector (
1727 IN UINT64 FirstFwVSize
1731 Routine Description:
1733 Update the 16 byte IA32 Reset vector to maintain the compatibility
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..
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.
1750 UINT8
*LocalVtfBuffer
;
1754 if (!strcmp (FileName
, "")) {
1755 return EFI_INVALID_PARAMETER
;
1758 Fp
= fopen (LongFilePath (FileName
), "rb");
1761 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1765 FileSize
= _filelength (fileno (Fp
));
1767 if (FileSize
> 16) {
1771 Buffer
= malloc (FileSize
);
1772 if (Buffer
== NULL
) {
1773 return EFI_OUT_OF_RESOURCES
;
1776 fread (Buffer
, sizeof (UINT8
), FileSize
, Fp
);
1778 LocalVtfBuffer
= (UINT8
*) Vtf1EndBuffer
- SIZE_IA32_RESET_VECT
;
1779 memcpy (LocalVtfBuffer
, Buffer
, FileSize
);
1797 Routine Description:
1799 This function cleans up any allocated buffer
1811 PARSED_VTF_INFO
*TempFileListPtr
;
1822 // Cleanup the buffer which was allocated to read the file names from FV.INF
1824 FileListPtr
= FileListHeadPtr
;
1825 while (FileListPtr
!= NULL
) {
1826 TempFileListPtr
= FileListPtr
->NextVtfInfo
;
1828 FileListPtr
= TempFileListPtr
;
1833 ProcessAndCreateVtf (
1838 Routine Description:
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
1845 Size - Size of the Firmware Volume of which, this VTF belongs to.
1849 EFI_UNSUPPORTED - Unknown FIT type
1850 EFI_SUCCESS - The function completed successfully
1855 PARSED_VTF_INFO
*ParsedInfoPtr
;
1857 Status
= EFI_SUCCESS
;
1859 ParsedInfoPtr
= FileListHeadPtr
;
1861 while (ParsedInfoPtr
!= NULL
) {
1863 switch (ParsedInfoPtr
->CompType
) {
1865 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1867 case COMP_TYPE_FIT_HEADER
:
1868 //COMP_TYPE_FIT_HEADER 0x00
1869 Status
= CreateFitTableAndInitialize (ParsedInfoPtr
);
1873 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1875 case COMP_TYPE_FIT_PAL_A
:
1876 //COMP_TYPE_FIT_PAL_A 0x0F
1877 Status
= CreateAndUpdatePAL_A (ParsedInfoPtr
);
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
1885 if (Status
== EFI_SUCCESS
) {
1886 UpdateFitEntryForFwVolume (Size
);
1890 case COMP_TYPE_FIT_FV_BOOT
:
1891 //COMP_TYPE_FIT_FV_BOOT 0x7E
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
1897 Status
= EFI_SUCCESS
;
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.
1906 Status
= CreateAndUpdateComponent (ParsedInfoPtr
);
1907 if (EFI_ERROR (Status
)) {
1908 Error (NULL
, 0, 0002, "Error updating component", ParsedInfoPtr
->CompName
);
1914 ParsedInfoPtr
= ParsedInfoPtr
->NextVtfInfo
;
1921 IN UINT64 StartAddress1
,
1923 IN UINT64 StartAddress2
,
1929 Routine Description:
1931 This is the main function which will be called from application.
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
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
1948 UpdateIA32ResetVector
1957 Status
= EFI_UNSUPPORTED
;
1960 if (StartAddress2
== 0) {
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!");
1976 return EFI_INVALID_PARAMETER
;
1980 // The image buffer for the First VTF
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
;
1987 memset (Vtf1Buffer
, 0x00, (UINTN
) Size1
);
1988 Vtf1EndBuffer
= (UINT8
*) Vtf1Buffer
+ Size1
;
1989 Vtf1LastStartAddress
= Fv1EndAddress
| IPF_CACHE_BIT
;
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!");
2001 return EFI_INVALID_PARAMETER
;
2005 // The image buffer for the second VTF
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
;
2012 memset (Vtf2Buffer
, 0x00, (UINTN
) Size2
);
2013 Vtf2EndBuffer
= (UINT8
*) Vtf2Buffer
+ Size2
;
2014 Vtf2LastStartAddress
= Fv2EndAddress
| IPF_CACHE_BIT
;
2017 Status
= GetVtfRelatedInfoFromInfFile (VtfFP
);
2019 if (Status
!= EFI_SUCCESS
) {
2020 Error (NULL
, 0, 0003, "Error parsing file", "the input file.");
2025 Status
= ProcessAndCreateVtf (Size1
);
2026 if (Status
!= EFI_SUCCESS
) {
2031 if (SectionOptionFlag
) {
2032 Status
= UpdateIA32ResetVector (IA32BinFile
, Vtf1TotalSize
);
2033 if (Status
!= EFI_SUCCESS
) {
2040 // Re arrange the FIT Table for Ascending order of their FIT Type..
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.
2049 CalculateFitTableChecksum ();
2052 // Write the FFS header
2054 Vtf1TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2055 Vtf1LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2057 Status
= UpdateFfsHeader (Vtf1TotalSize
, FIRST_VTF
);
2058 if (Status
!= EFI_SUCCESS
) {
2063 // Update the VTF buffer into specified VTF binary file
2065 Status
= WriteVtfBinary (OutFileName1
, Vtf1TotalSize
, FIRST_VTF
);
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
) {
2077 // Update the VTF buffer into specified VTF binary file
2079 Status
= WriteVtfBinary (OutFileName2
, Vtf2TotalSize
, SECOND_VTF
);
2088 PeimFixupInFitTable (
2089 IN UINT64 StartAddress
2093 Routine Description:
2095 This function is an entry point to fixup SAL-E entry point.
2099 StartAddress - StartAddress for PEIM.....
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.
2111 UINT64
*StartAddressPtr
;
2114 StartAddressPtr
= malloc (sizeof (UINT64
));
2115 if (StartAddressPtr
== NULL
) {
2116 return EFI_OUT_OF_RESOURCES
;
2118 *StartAddressPtr
= StartAddress
;
2120 Fp
= fopen (LongFilePath (OutFileName1
), "rb");
2123 Error (NULL
, 0, 0001, "Error opening file", OutFileName1
);
2124 if (StartAddressPtr
) {
2125 free (StartAddressPtr
);
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
);
2138 if (StartAddressPtr
) {
2139 free (StartAddressPtr
);
2142 Status
= EFI_SUCCESS
;
2148 IN UINT64 BaseAddress
,
2149 IN CHAR8
*DestFileName
,
2150 IN CHAR8
*SourceFileName
,
2156 Routine Description:
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.
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.
2170 EFI_SUCCESS - The function completed successfully.
2171 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2172 EFI_ABORTED - An error occurred.
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
;
2188 // Verify input parameters.
2190 if (BaseAddress
== 0 || DestFileName
== NULL
|| SourceFileName
== NULL
) {
2191 return EFI_INVALID_PARAMETER
;
2195 // Open the source file
2197 SourceFile
= fopen (LongFilePath (SourceFileName
), "r");
2198 if (SourceFile
== NULL
) {
2201 // SYM files are not required.
2207 // Use the file name minus extension as the base for tokens
2209 strcpy (BaseToken
, SourceFileName
);
2210 strtok (BaseToken
, ". \t\n");
2211 strcat (BaseToken
, "__");
2214 // Open the destination file
2216 DestFile
= fopen (LongFilePath (DestFileName
), "a+");
2217 if (DestFile
== NULL
) {
2218 fclose (SourceFile
);
2219 Error (NULL
, 0, 0001, "Error opening file", DestFileName
);
2224 // If this is the beginning of the output file, write the symbol format info.
2226 if (fseek (DestFile
, 0, SEEK_END
) != 0) {
2227 fclose (SourceFile
);
2229 Error (NULL
, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2233 StartLocation
= ftell (DestFile
);
2235 if (StartLocation
== 0) {
2236 fprintf (DestFile
, "TEXTSYM format | V1.0\n");
2237 } else if (StartLocation
== -1) {
2238 fclose (SourceFile
);
2240 Error (NULL
, 0, 2000, "Invalid parameter", "StartLocation error");
2245 // Read the first line
2247 if (fgets (Buffer
, MAX_LONG_FILE_PATH
, SourceFile
) == NULL
) {
2252 // Make sure it matches the expected sym format
2254 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
2255 fclose (SourceFile
);
2257 Error (NULL
, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2264 while (feof (SourceFile
) == 0) {
2269 if (fscanf (SourceFile
, "%s | %s | %s | %s\n", Type
, Address
, Section
, Token
) == 4) {
2272 // Get the token address
2274 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
2275 if (TokenAddress
> FileSize
) {
2277 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2283 // Add the base address, the size of the FFS file header and the size of the peim header.
2285 TokenAddress
+= BaseAddress
&~IPF_CACHE_BIT
;
2287 fprintf (DestFile
, "%s | %016llX | ", Type
, (unsigned long long) TokenAddress
);
2288 fprintf (DestFile
, "%s | %s\n %s\n", Section
, Token
, BaseToken
);
2292 fclose (SourceFile
);
2298 CalculateFitTableChecksum (
2303 Routine Description:
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;.
2315 Status - Value returned by call to CalculateChecksum8 ()
2316 EFI_SUCCESS - The function completed successfully
2320 FIT_TABLE
*TmpFitPtr
;
2322 UINT64 FitTableAddOffset
;
2323 UINTN RelativeAddress
;
2327 // Read the Fit Table address from Itanium-based address map.
2329 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
2332 // Translate this Itanium-based address in terms of local buffer address which
2333 // contains the image for Boot Strapped File
2335 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
2336 FitTableAdd
= *(UINTN
*) RelativeAddress
;
2338 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
2340 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
2342 Size
= TmpFitPtr
->CompSize
* 16;
2344 if ((TmpFitPtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2345 TmpFitPtr
->CheckSum
= 0;
2346 TmpFitPtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) TmpFitPtr
, Size
);
2348 TmpFitPtr
->CheckSum
= 0;
2360 Routine Description:
2362 Displays the standard utility information to SDTOUT
2374 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
2383 Routine Description:
2385 Displays the utility usage syntax to STDOUT
2400 fprintf (stdout
, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME
);
2403 // Copyright declaration
2405 fprintf (stdout
, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
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");
2433 Routine Description:
2435 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2436 part of firmware volume image.
2440 argc - The count of the parameters
2441 argv - The parameters
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
2457 UINT64 StartAddress1
;
2458 UINT64 StartAddress2
;
2461 BOOLEAN FirstRoundO
;
2462 BOOLEAN FirstRoundB
;
2463 BOOLEAN FirstRoundS
;
2468 SetUtilityName (UTILITY_NAME
);
2471 // Initialize variables
2481 OutFileName1
= NULL
;
2482 OutFileName2
= NULL
;
2487 // Verify the correct number of arguments
2494 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
2499 if ((strcmp(argv
[1], "--version") == 0)) {
2505 // Parse the command line arguments
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");
2514 // Get the output file name
2519 // It's the first output file name
2521 OutFileName1
= (CHAR8
*)argv
[Index
+1];
2522 FirstRoundO
= FALSE
;
2525 //It's the second output file name
2527 OutFileName2
= (CHAR8
*)argv
[Index
+1];
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");
2538 // Get the input VTF file name
2540 VtfFileName
= argv
[Index
+1];
2541 VtfFP
= fopen (LongFilePath (VtfFileName
), "rb");
2542 if (VtfFP
== NULL
) {
2543 Error (NULL
, 0, 0001, "Error opening file", VtfFileName
);
2549 if ((stricmp (argv
[Index
], "-r") == 0) || (stricmp (argv
[Index
], "--baseaddr") == 0)) {
2551 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress1
);
2552 FirstRoundB
= FALSE
;
2554 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress2
);
2556 if (Status
!= EFI_SUCCESS
) {
2557 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv
[Index
+ 1]);
2563 if ((stricmp (argv
[Index
], "-s") == 0) || (stricmp (argv
[Index
], "--size") == 0)) {
2565 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize1
);
2566 FirstRoundS
= FALSE
;
2568 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize2
);
2572 if (Status
!= EFI_SUCCESS
) {
2573 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv
[Index
+ 1]);
2579 if ((stricmp (argv
[Index
], "-v") == 0) || (stricmp (argv
[Index
], "--verbose") == 0)) {
2585 if ((stricmp (argv
[Index
], "-q") == 0) || (stricmp (argv
[Index
], "--quiet") == 0)) {
2591 if ((stricmp (argv
[Index
], "-d") == 0) || (stricmp (argv
[Index
], "--debug") == 0)) {
2593 // debug level specified
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]);
2600 if (DebugLevel
> 9) {
2601 Error (NULL
, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv
[Index
+ 1]);
2604 if((DebugLevel
<= 9) &&(DebugLevel
>= 5)) {
2612 Error (NULL
, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv
[Index
]);
2616 if (VtfFP
== NULL
) {
2617 Error (NULL
, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2622 Error (NULL
, 0, 2000, "Invalid parameter", "No FV base address is specified");
2627 Error (NULL
, 0, 2000, "Invalid parameter", "No FV Size is specified");
2631 // All Parameters has been parsed, now set the message print level
2635 } else if (VerboseMode
) {
2637 } else if (DebugMode
) {
2638 SetPrintLevel(DebugLevel
);
2642 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
2645 if (VTF_OUTPUT
== FALSE
) {
2646 if (SecondVTF
== TRUE
) {
2647 OutFileName1
= VTF_OUTPUT_FILE1
;
2648 OutFileName2
= VTF_OUTPUT_FILE2
;
2650 OutFileName1
= VTF_OUTPUT_FILE1
;
2652 SymFileName
= VTF_SYM_FILE
;
2654 INTN OutFileNameLen
= strlen(OutFileName1
);
2657 for (Index
= OutFileNameLen
; Index
> 0; --Index
) {
2658 if (OutFileName1
[Index
] == '/' || OutFileName1
[Index
] == '\\') {
2663 SymFileName
= VTF_SYM_FILE
;
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';
2672 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, SymFileName
, NULL
);
2677 // Call the GenVtfImage
2680 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Start to generate the VTF image\n", NULL
);
2682 Status
= GenerateVtfImage (StartAddress1
, FwVolSize1
, StartAddress2
, FwVolSize2
, VtfFP
);
2684 if (EFI_ERROR (Status
)) {
2687 case EFI_INVALID_PARAMETER
:
2688 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2692 Error (NULL
, 0, 3000, "Invalid", "Error detected while creating the file image.");
2695 case EFI_OUT_OF_RESOURCES
:
2696 Error (NULL
, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2699 case EFI_VOLUME_CORRUPTED
:
2700 Error (NULL
, 0, 3000, "Invalid", "No base address was specified.");
2704 Error (NULL
, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status
);
2709 if (VtfFP
!= NULL
) {
2714 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "VTF image generated successful\n", NULL
);
2718 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2720 return GetUtilityStatus();