3 Copyright (c) 1999-2008 Intel Corporation. All rights reserved
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
;
345 Warning(UTILITY_NAME
, 0, 0001, "Unknown location for component.", VtfInfo
->CompName
);
347 } else if (strnicmp (*TokenStr
, "COMP_TYPE", 9) == 0) {
349 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
350 Error (NULL
, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr
);
354 VtfInfo
->CompType
= (UINT8
) StringValue
;
355 } else if (strnicmp (*TokenStr
, "COMP_VER", 8) == 0) {
357 if (strnicmp (*TokenStr
, "-", 1) == 0) {
358 VtfInfo
->VersionPresent
= FALSE
;
359 VtfInfo
->MajorVer
= 0;
360 VtfInfo
->MinorVer
= 0;
362 VtfInfo
->VersionPresent
= TRUE
;
363 ConvertVersionInfo (*TokenStr
, &VtfInfo
->MajorVer
, &VtfInfo
->MinorVer
);
365 } else if (strnicmp (*TokenStr
, "COMP_BIN", 8) == 0) {
367 strcpy (VtfInfo
->CompBinName
, *TokenStr
);
368 } else if (strnicmp (*TokenStr
, "COMP_SYM", 8) == 0) {
370 strcpy (VtfInfo
->CompSymName
, *TokenStr
);
371 } else if (strnicmp (*TokenStr
, "COMP_SIZE", 9) == 0) {
373 if (strnicmp (*TokenStr
, "-", 1) == 0) {
374 VtfInfo
->PreferredSize
= FALSE
;
375 VtfInfo
->CompSize
= 0;
377 VtfInfo
->PreferredSize
= TRUE
;
378 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
379 Error (NULL
, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr
);
383 VtfInfo
->CompSize
= (UINTN
) StringValue
;
386 } else if (strnicmp (*TokenStr
, "COMP_CS", 7) == 0) {
388 if (strnicmp (*TokenStr
, "1", 1) == 0) {
389 VtfInfo
->CheckSumRequired
= 1;
390 } else if (strnicmp (*TokenStr
, "0", 1) == 0) {
391 VtfInfo
->CheckSumRequired
= 0;
393 Error (NULL
, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
398 if (*TokenStr
== NULL
) {
405 InitializeInFileInfo (
412 This function intializes the relevant global variable which is being
413 used to store the information retrieved from INF file.
426 SectionOptionFlag
= 0;
428 TokenStr
= OrgStrTokPtr
;
430 while (*TokenStr
!= NULL
) {
431 if (strnicmp (*TokenStr
, "[OPTIONS]", 9) == 0) {
432 SectionOptionFlag
= 1;
436 if (strnicmp (*TokenStr
, "[COMPONENTS]", 12) == 0) {
437 if (FileListPtr
== NULL
) {
438 FileListPtr
= FileListHeadPtr
;
442 SectionOptionFlag
= 0;
446 if (SectionOptionFlag
) {
447 if (stricmp (*TokenStr
, "IA32_RST_BIN") == 0) {
449 strcpy (IA32BinFile
, *TokenStr
);
453 if (SectionCompFlag
) {
454 if (stricmp (*TokenStr
, "COMP_NAME") == 0) {
456 strcpy (FileListPtr
->CompName
, *TokenStr
);
458 ParseAndUpdateComponents (FileListPtr
);
461 if (*TokenStr
!= NULL
) {
462 FileListPtr
->NextVtfInfo
= malloc (sizeof (PARSED_VTF_INFO
));
463 if (FileListPtr
->NextVtfInfo
== NULL
) {
464 Error (NULL
, 0, 4003, "Resource", "Out of memory resources.", NULL
);
467 FileListPtr
= FileListPtr
->NextVtfInfo
;
468 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
469 FileListPtr
->NextVtfInfo
= NULL
;
481 GetVtfRelatedInfoFromInfFile (
488 This function reads the input file, parse it and create a list of tokens
489 which is parsed and used, to intialize the data related to VTF
493 FileName - FileName which needed to be read to parse data
497 EFI_ABORTED - Error in opening file
498 EFI_INVALID_PARAMETER - File doesn't contain any valid information
499 EFI_OUT_OF_RESOURCES - Malloc Failed
500 EFI_SUCCESS - The function completed successfully
509 Status
= EFI_SUCCESS
;
512 Error (NULL
, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
518 if (ValidLineNum
== 0) {
519 Error (NULL
, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
520 return EFI_INVALID_PARAMETER
;
523 TokenStr
= (CHAR8
**) malloc (sizeof (UINTN
) * (2 * ValidLineNum
+ 1));
525 if (TokenStr
== NULL
) {
526 return EFI_OUT_OF_RESOURCES
;
529 memset (TokenStr
, 0, (sizeof (UINTN
) * (2 * ValidLineNum
+ 1)));
530 OrgStrTokPtr
= TokenStr
;
532 for (Index
= 0; Index
< (2 * ValidLineNum
); Index
++) {
533 *TokenStr
= (CHAR8
*)malloc (sizeof (CHAR8
) * FILE_NAME_SIZE
);
535 if (*TokenStr
== NULL
) {
536 Status
= EFI_OUT_OF_RESOURCES
;
540 memset (*TokenStr
, 0, FILE_NAME_SIZE
);
544 TokenStr
= OrgStrTokPtr
;
545 fseek (Fp
, 0L, SEEK_SET
);
547 Status
= InitializeComps ();
549 if (Status
!= EFI_SUCCESS
) {
553 Status
= ParseInputFile (Fp
);
554 if (Status
!= EFI_SUCCESS
) {
558 InitializeInFileInfo ();
562 for (Index1
= 0; Index1
< Index
; Index1
++) {
563 free (OrgStrTokPtr
[Index1
]);
572 GetRelativeAddressInVtfBuffer (
574 IN OUT UINTN
*RelativeAddress
,
581 This function checks for the address alignmnet for specified data boundary. In
582 case the address is not aligned, it returns FALSE and the amount of data in
583 terms of byte needed to adjust to get the boundary alignmnet. If data is
584 aligned, TRUE will be returned.
588 Address - The address of the flash map space
589 RelativeAddress - The relative address of the Buffer
590 LocType - The type of the VTF
601 if (LocType
== FIRST_VTF
) {
602 LocalBuff
= (UINT8
*) Vtf1EndBuffer
;
603 TempAddress
= Fv1EndAddress
- Address
;
604 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
606 LocalBuff
= (UINT8
*) Vtf2EndBuffer
;
607 TempAddress
= Fv2EndAddress
- Address
;
608 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
613 GetComponentVersionInfo (
614 IN OUT PARSED_VTF_INFO
*VtfInfo
,
620 This function will extract the version information from File
624 VtfInfo - A Pointer to the VTF Info Structure
625 Buffer - A Pointer to type UINT8
629 EFI_SUCCESS - The function completed successfully
630 EFI_INVALID_PARAMETER - The parameter is invalid
637 switch (VtfInfo
->CompType
) {
639 case COMP_TYPE_FIT_PAL_A
:
640 case COMP_TYPE_FIT_PAL_B
:
641 memcpy (&VersionInfo
, (Buffer
+ 8), sizeof (UINT16
));
642 VtfInfo
->MajorVer
= (UINT8
) ((VersionInfo
& 0xFF00) >> 8);
643 VtfInfo
->MinorVer
= (UINT8
) (VersionInfo
& 0x00FF);
644 Status
= EFI_SUCCESS
;
648 Status
= EFI_INVALID_PARAMETER
;
656 CheckAddressAlignment (
658 IN UINT64 AlignmentData
,
659 IN OUT UINT64
*AlignAdjustByte
665 This function checks for the address alignmnet for specified data boundary. In
666 case the address is not aligned, it returns FALSE and the amount of data in
667 terms of byte needed to adjust to get the boundary alignmnet. If data is
668 aligned, TRUE will be returned.
672 Address - Pointer to buffer containing byte data of component.
673 AlignmentData - DataSize for which address needed to be aligned
674 AlignAdjustByte - Number of bytes needed to adjust alignment.
678 TRUE - Address is aligned to specific data size boundary
679 FALSE - Address in not aligned to specified data size boundary
680 - Add/Subtract AlignAdjustByte to aling the address.
685 // Check if the assigned address is on address boundary. If not, it will
686 // return the remaining byte required to adjust the address for specified
689 *AlignAdjustByte
= (Address
% AlignmentData
);
691 if (*AlignAdjustByte
== 0) {
699 GetFitTableStartAddress (
700 IN OUT FIT_TABLE
**FitTable
706 Get the FIT table start address in VTF Buffer
710 FitTable - Pointer to available fit table where new component can be added
714 EFI_SUCCESS - The function completed successfully
719 UINT64 FitTableAddOffset
;
720 UINTN RelativeAddress
;
723 // Read the Fit Table address from Itanium-based address map.
725 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
728 // Translate this Itanium-based address in terms of local buffer address which
729 // contains the image for Boot Strapped File. The relative address will be
730 // the address of fit table VTF buffer.
732 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
733 FitTableAdd
= *(UINTN
*) RelativeAddress
;
736 // The FitTableAdd is the extracted Itanium based address pointing to FIT
737 // table. The relative address will return its actual location in VTF
740 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
742 *FitTable
= (FIT_TABLE
*) RelativeAddress
;
748 GetNextAvailableFitPtr (
749 IN FIT_TABLE
**FitPtr
755 Get the FIT table address and locate the free space in fit where we can add
756 new component. In this process, this function locates the fit table using
757 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
758 and locate the available location in FIT table to be used by new components.
759 If there are any Fit table which areg not being used contains ComponentType
760 field as 0x7F. If needed we can change this and spec this out.
764 FitPtr - Pointer to available fit table where new component can be added
768 EFI_SUCCESS - The function completed successfully
772 FIT_TABLE
*TmpFitPtr
;
774 UINT64 FitTableAddOffset
;
776 UINTN NumFitComponents
;
777 UINTN RelativeAddress
;
780 // Read the Fit Table address from Itanium-based address map.
782 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
785 // Translate this Itanium-based address in terms of local buffer address which
786 // contains the image for Boot Strapped File. The relative address will be
787 // the address of fit table VTF buffer.
789 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
790 FitTableAdd
= *(UINTN
*) RelativeAddress
;
793 // The FitTableAdd is the extracted Itanium based address pointing to FIT
794 // table. The relative address will return its actual location in VTF
797 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
799 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
800 NumFitComponents
= TmpFitPtr
->CompSize
;
802 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
803 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_UNUSED
) {
823 This function is used by qsort to sort the FIT table based upon Component
824 Type in their incresing order.
828 Arg1 - Pointer to Arg1
829 Arg2 - Pointer to Arg2
837 if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) > (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
839 } else if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) < (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
854 This function is used by qsort to sort the FIT table based upon Component
855 Type in their incresing order.
868 FIT_TABLE
*TmpFitPtr
;
869 UINTN NumFitComponents
;
872 GetFitTableStartAddress (&FitTable
);
873 TmpFitPtr
= FitTable
;
874 NumFitComponents
= 0;
875 for (Index
= 0; Index
< FitTable
->CompSize
; Index
++) {
876 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) != COMP_TYPE_FIT_UNUSED
) {
877 NumFitComponents
+= 1;
881 qsort ((VOID
*) FitTable
, NumFitComponents
, sizeof (FIT_TABLE
), CompareItems
);
885 UpdateFitEntryForFwVolume (
892 This function updates the information about Firmware Volume in FIT TABLE.
893 This FIT table has to be immediately below the PAL_A Start and it contains
894 component type and address information. Other information can't be
895 created this time so we would need to fix it up..
900 Size - Firmware Volume Size
908 FIT_TABLE
*CompFitPtr
;
909 UINTN RelativeAddress
;
912 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
914 Vtf1LastStartAddress
-= 0x10;
915 Vtf1TotalSize
+= 0x10;
917 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
919 CompFitPtr
= (FIT_TABLE
*) RelativeAddress
;
920 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
923 // Since we don't have any information about its location in Firmware Volume,
924 // initialize address to 0. This will be updated once Firmware Volume is
925 // being build and its current address will be fixed in FIT table. Currently
926 // we haven't implemented it so far and working on architectural clarafication
929 // Firmware Volume Size in 16 byte block
931 CompFitPtr
->CompSize
= ((UINT32
) Size
) / 16;
934 // Since Firmware Volume does not exist by the time we create this FIT info
935 // this should be fixedup from Firmware Volume creation tool. We haven't
936 // worked out a method so far.
938 CompFitPtr
->CompVersion
= MAKE_VERSION (0, 0);
941 // Since we don't have any info about this file, we are making sure that
942 // checksum is not needed.
944 CompFitPtr
->CvAndType
= CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT
);
947 // Since non VTF component will reside outside the VTF, we will not have its
948 // binary image while creating VTF, hence we will not perform checksum at
949 // this time. Once Firmware Volume is being created which will contain this
950 // VTF, it will fix the FIT table for all the non VTF component and hence
953 CompFitPtr
->CheckSum
= 0;
957 UpdateFitEntryForNonVTFComp (
958 IN PARSED_VTF_INFO
*VtfInfo
964 This function updates the information about non VTF component in FIT TABLE.
965 Since non VTF componets binaries are not part of VTF binary, we would still
966 be required to update its location information in Firmware Volume, inside
971 VtfInfo - Pointer to VTF Info Structure
975 EFI_ABORTED - The function fails to update the component in FIT
976 EFI_SUCCESS - The function completed successfully
980 FIT_TABLE
*CompFitPtr
;
983 // Scan the FIT table for available space
985 GetNextAvailableFitPtr (&CompFitPtr
);
986 if (CompFitPtr
== NULL
) {
987 Error (NULL
, 0, 5003, "Invalid", "Can't update this component in FIT");
992 // Since we don't have any information about its location in Firmware Volume,
993 // initialize address to 0. This will be updated once Firmware Volume is
994 // being build and its current address will be fixed in FIT table
996 CompFitPtr
->CompAddress
= 0;
997 CompFitPtr
->CompSize
= VtfInfo
->CompSize
;
998 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
999 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1002 // Since non VTF component will reside outside the VTF, we will not have its
1003 // binary image while creating VTF, hence we will not perform checksum at
1004 // this time. Once Firmware Volume is being created which will contain this
1005 // VTF, it will fix the FIT table for all the non VTF component and hence
1008 CompFitPtr
->CheckSum
= 0;
1011 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
1012 // address of Firmware Volume in which this VTF will be attached.
1014 if ((CompFitPtr
->CvAndType
& 0x7F) == COMP_TYPE_FIT_FV_BOOT
) {
1015 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
1023 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
1024 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
1025 // CORE moves in Firmware Volume, we would need to modify this function to be
1026 // used with a API which will detect PEICORE component while building Firmware
1027 // Volume and update its entry in FIT table as well as in Itanium address space
1028 // as per Intel?Itanium(TM) SAL address space
1032 IN PARSED_VTF_INFO
*VtfInfo
,
1033 IN UINT64
*CompStartAddress
1037 Routine Description:
1039 This function updated the architectural entry point in IPF, SALE_ENTRY.
1043 VtfInfo - Pointer to VTF Info Structure
1044 CompStartAddress - Pointer to Component Start Address
1048 EFI_INVALID_PARAMETER - The parameter is invalid
1049 EFI_SUCCESS - The function completed successfully
1053 UINTN RelativeAddress
;
1058 CHAR8 Buff
[FILE_NAME_SIZE
];
1061 CHAR8 OffsetStr
[30];
1067 Fp
= fopen (VtfInfo
->CompSymName
, "rb");
1070 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompSymName
);
1071 return EFI_INVALID_PARAMETER
;
1074 while (fgets (Buff
, sizeof (Buff
), Fp
) != NULL
) {
1077 "%s %s %s %s %s %s %s",
1086 if (strnicmp (Token
, "SALE_ENTRY", 10) == 0) {
1091 Offset
= strtoul (OffsetStr
, NULL
, 16);
1093 *CompStartAddress
+= Offset
;
1094 SalEntryAdd
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
);
1096 GetRelativeAddressInVtfBuffer (SalEntryAdd
, &RelativeAddress
, FIRST_VTF
);
1098 memcpy ((VOID
*) RelativeAddress
, (VOID
*) CompStartAddress
, sizeof (UINT64
));
1108 CreateAndUpdateComponent (
1109 IN PARSED_VTF_INFO
*VtfInfo
1113 Routine Description:
1115 This function reads the binary file for each components and update them
1116 in VTF Buffer as well as in FIT table. If the component is located in non
1117 VTF area, only the FIT table address will be updated
1121 VtfInfo - Pointer to Parsed Info
1125 EFI_SUCCESS - The function completed successful
1126 EFI_ABORTED - Aborted due to one of the many reasons like:
1127 (a) Component Size greater than the specified size.
1128 (b) Error opening files.
1130 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1131 EFI_OUT_OF_RESOURCES Memory allocation failure.
1136 UINT64 CompStartAddress
;
1139 UINT64 NumAdjustByte
;
1142 FIT_TABLE
*CompFitPtr
;
1145 if (VtfInfo
->LocationType
== NONE
) {
1146 UpdateFitEntryForNonVTFComp (VtfInfo
);
1150 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1153 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1157 FileSize
= _filelength (fileno (Fp
));
1158 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1161 // BUGBUG: Satish to correct
1163 FileSize
-= SIZE_OF_PAL_HEADER
;
1166 if (VtfInfo
->PreferredSize
) {
1167 if (FileSize
> VtfInfo
->CompSize
) {
1168 Error (NULL
, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1172 FileSize
= VtfInfo
->CompSize
;
1175 Buffer
= malloc ((UINTN
) FileSize
);
1176 if (Buffer
== NULL
) {
1177 return EFI_OUT_OF_RESOURCES
;
1179 memset (Buffer
, 0, (UINTN
) FileSize
);
1181 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1184 // Read first 64 bytes of PAL header and use it to find version info
1186 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1189 // PAL header contains the version info. Currently, we will use the header
1190 // to read version info and then discard.
1192 if (!VtfInfo
->VersionPresent
) {
1193 GetComponentVersionInfo (VtfInfo
, Buffer
);
1197 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1201 // If it is non PAL_B component, pass the entire buffer to get the version
1202 // info and implement any specific case inside GetComponentVersionInfo.
1204 if (VtfInfo
->CompType
!= COMP_TYPE_FIT_PAL_B
) {
1205 if (!VtfInfo
->VersionPresent
) {
1206 GetComponentVersionInfo (VtfInfo
, Buffer
);
1210 if (VtfInfo
->LocationType
== SECOND_VTF
) {
1212 CompStartAddress
= (Vtf2LastStartAddress
- FileSize
);
1214 CompStartAddress
= (Vtf1LastStartAddress
- FileSize
);
1217 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) {
1218 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 32 * 1024, &NumAdjustByte
);
1220 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 8, &NumAdjustByte
);
1224 CompStartAddress
-= NumAdjustByte
;
1227 if (VtfInfo
->LocationType
== SECOND_VTF
&& SecondVTF
== TRUE
) {
1228 Vtf2LastStartAddress
= CompStartAddress
;
1229 Vtf2TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1230 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, SECOND_VTF
);
1231 } else if (VtfInfo
->LocationType
== FIRST_VTF
) {
1232 Vtf1LastStartAddress
= CompStartAddress
;
1233 Vtf1TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1234 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1236 Error (NULL
, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
1237 return EFI_INVALID_PARAMETER
;
1240 if (EFI_ERROR (Status
)) {
1244 GetNextAvailableFitPtr (&CompFitPtr
);
1246 CompFitPtr
->CompAddress
= CompStartAddress
| IPF_CACHE_BIT
;
1247 if ((FileSize
% 16) != 0) {
1248 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1249 return EFI_INVALID_PARAMETER
;
1251 //assert ((FileSize % 16) == 0);
1252 CompFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1253 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1254 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1255 if (VtfInfo
->CheckSumRequired
) {
1256 CompFitPtr
->CheckSum
= 0;
1257 CompFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1268 // Update the SYM file for this component based on it's start address.
1270 Status
= UpdateSymFile (CompStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1271 if (EFI_ERROR (Status
)) {
1274 // At this time, SYM files are not required, so continue on error.
1278 // !!!!!!!!!!!!!!!!!!!!!
1280 // This part of the code is a temporary line since PEICORE is going to be inside
1281 // VTF till we work out how to determine the SALE_ENTRY through it. We will need
1282 // to clarify so many related questions
1283 // !!!!!!!!!!!!!!!!!!!!!!!
1285 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PEICORE
) {
1286 Status
= UpdateEntryPoint (VtfInfo
, &CompStartAddress
);
1293 CreateAndUpdatePAL_A (
1294 IN PARSED_VTF_INFO
*VtfInfo
1298 Routine Description:
1300 This function reads the binary file for each components and update them
1301 in VTF Buffer as well as FIT table
1305 VtfInfo - Pointer to Parsed Info
1309 EFI_ABORTED - Due to one of the following reasons:
1310 (a)Error Opening File
1311 (b)The PAL_A Size is more than specified size status
1312 One of the values mentioned below returned from
1313 call to UpdateSymFile
1314 EFI_SUCCESS - The function completed successfully.
1315 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
1316 EFI_ABORTED - An error occurred.UpdateSymFile
1317 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1322 UINT64 PalStartAddress
;
1324 UINTN RelativeAddress
;
1329 FIT_TABLE
*PalFitPtr
;
1331 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1334 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1338 FileSize
= _filelength (fileno (Fp
));
1339 if (FileSize
< 64) {
1340 Error (NULL
, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
1341 return EFI_INVALID_PARAMETER
;
1343 FileSize
-= SIZE_OF_PAL_HEADER
;
1346 if (VtfInfo
->PreferredSize
) {
1347 if (FileSize
> VtfInfo
->CompSize
) {
1348 Error (NULL
, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
1352 FileSize
= VtfInfo
->CompSize
;
1355 Buffer
= malloc ((UINTN
) FileSize
);
1356 if (Buffer
== NULL
) {
1357 return EFI_OUT_OF_RESOURCES
;
1359 memset (Buffer
, 0, (UINTN
) FileSize
);
1362 // Read, Get version Info and discard the PAL header.
1364 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1367 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1369 if (!VtfInfo
->VersionPresent
) {
1370 GetComponentVersionInfo (VtfInfo
, Buffer
);
1374 // Read PAL_A file in a buffer
1376 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1379 PalStartAddress
= Fv1EndAddress
- (SIZE_TO_OFFSET_PAL_A_END
+ FileSize
);
1380 Vtf1LastStartAddress
= PalStartAddress
;
1381 Vtf1TotalSize
+= (UINT32
) FileSize
;
1382 Status
= UpdateVtfBuffer (PalStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1384 AbsAddress
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1385 GetRelativeAddressInVtfBuffer (AbsAddress
, &RelativeAddress
, FIRST_VTF
);
1386 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1387 PalFitPtr
->CompAddress
= PalStartAddress
| IPF_CACHE_BIT
;
1388 //assert ((FileSize % 16) == 0);
1389 if ((FileSize
% 16) != 0) {
1390 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1391 return EFI_INVALID_PARAMETER
;
1394 PalFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1395 PalFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1396 PalFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1397 if (VtfInfo
->CheckSumRequired
) {
1398 PalFitPtr
->CheckSum
= 0;
1399 PalFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1407 // Update the SYM file for this component based on it's start address.
1409 Status
= UpdateSymFile (PalStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1410 if (EFI_ERROR (Status
)) {
1413 // At this time, SYM files are not required, so continue on error.
1421 CreateFitTableAndInitialize (
1422 IN PARSED_VTF_INFO
*VtfInfo
1426 Routine Description:
1428 This function creates and intializes FIT table which would be used to
1429 add component info inside this
1433 VtfInfo - Pointer to Parsed Info
1437 EFI_ABORTED - Aborted due to no size information
1438 EFI_SUCCESS - The function completed successfully
1442 UINT64 PalFitTableAdd
;
1444 UINT64 FitTableAddressOffset
;
1445 FIT_TABLE
*PalFitPtr
;
1446 FIT_TABLE
*FitStartPtr
;
1448 UINTN RelativeAddress
;
1451 if (!VtfInfo
->PreferredSize
) {
1452 Error (NULL
, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1456 if ((VtfInfo
->CompSize
% 16) != 0) {
1457 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
1460 PalFitTableAdd
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1461 GetRelativeAddressInVtfBuffer (PalFitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1462 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1463 PalFitTableAdd
= (PalFitPtr
->CompAddress
- VtfInfo
->CompSize
);
1465 FitTableAdd
= (PalFitPtr
->CompAddress
- 0x10) - VtfInfo
->CompSize
;
1466 FitTableAddressOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
1467 GetRelativeAddressInVtfBuffer (FitTableAddressOffset
, &RelativeAddress
, FIRST_VTF
);
1468 *(UINT64
*) RelativeAddress
= FitTableAdd
;
1470 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1473 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1475 FitStartPtr
= (FIT_TABLE
*) RelativeAddress
;
1477 strncpy ((CHAR8
*) &FitStartPtr
->CompAddress
, FIT_SIGNATURE
, 8); // "_FIT_ "
1478 assert (((VtfInfo
->CompSize
& 0x00FFFFFF) % 16) == 0);
1479 FitStartPtr
->CompSize
= (VtfInfo
->CompSize
& 0x00FFFFFF) / 16;
1480 FitStartPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1483 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1484 // determine what to do for things like the FV component that aren't easily checksummed.
1485 // The checksum will be done once we are done with all the componet update in the FIT
1488 FitStartPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1490 NumFitComp
= FitStartPtr
->CompSize
;
1495 // Intialize remaining FIT table space to UNUSED fit component type
1496 // so that when we need to create a FIT entry for a component, we can
1497 // locate a free one and use it.
1499 for (Index
= 0; Index
< (NumFitComp
- 1); Index
++) {
1500 FitStartPtr
->CvAndType
= 0x7F; // Initialize all with UNUSED
1504 Vtf1TotalSize
+= VtfInfo
->CompSize
;
1505 Vtf1LastStartAddress
-= VtfInfo
->CompSize
;
1518 Routine Description:
1520 Write Firmware Volume from memory to a file.
1524 FileName - Output File Name which needed to be created/
1526 LocType - The type of the VTF
1530 EFI_ABORTED - Returned due to one of the following resons:
1531 (a) Error Opening File
1532 (b) Failing to copy buffers
1533 EFI_SUCCESS - The fuction completes successfully
1540 UINTN RelativeAddress
;
1542 if (LocType
== FIRST_VTF
) {
1543 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1544 VtfBuffer
= (VOID
*) RelativeAddress
;
1546 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1547 VtfBuffer
= (VOID
*) RelativeAddress
;
1550 Fp
= fopen (FileName
, "wb");
1552 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1556 NumByte
= fwrite (VtfBuffer
, sizeof (UINT8
), (UINTN
) VtfSize
, Fp
);
1562 if (NumByte
!= (sizeof (UINT8
) * VtfSize
)) {
1563 Error (NULL
, 0, 0002, "Error writing file", FileName
);
1572 IN UINT64 StartAddress
,
1579 Routine Description:
1581 Update the Firmware Volume Buffer with requested buffer data
1585 StartAddress - StartAddress in buffer. This number will automatically
1586 point to right address in buffer where data needed
1588 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1589 DataSize - Size of the data needed to be copied.
1590 LocType - The type of the VTF: First or Second
1594 EFI_ABORTED - The input parameter is error
1595 EFI_SUCCESS - The function completed successfully
1599 UINT8
*LocalBufferPtrToWrite
;
1601 if (LocType
== FIRST_VTF
) {
1602 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf1LastStartAddress
| IPF_CACHE_BIT
)) {
1603 Error (NULL
, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
1607 LocalBufferPtrToWrite
= (UINT8
*) Vtf1EndBuffer
;
1609 LocalBufferPtrToWrite
-= (Fv1EndAddress
- StartAddress
);
1613 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf2LastStartAddress
| IPF_CACHE_BIT
)) {
1614 Error (NULL
, 0, 2000, "Invalid parameter", "Error StartAddress");
1617 LocalBufferPtrToWrite
= (UINT8
*) Vtf2EndBuffer
;
1618 LocalBufferPtrToWrite
-= (Fv2EndAddress
- StartAddress
);
1621 memcpy (LocalBufferPtrToWrite
, Buffer
, (UINTN
) DataSize
);
1628 IN UINT32 TotalVtfSize
,
1633 Routine Description:
1635 Update the Firmware Volume Buffer with requested buffer data
1639 TotalVtfSize - Size of the VTF
1640 Fileoffset - The start of the file relative to the start of the FV.
1641 LocType - The type of the VTF
1645 EFI_SUCCESS - The function completed successfully
1646 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1650 EFI_FFS_FILE_HEADER
*FileHeader
;
1651 UINTN RelativeAddress
;
1652 EFI_GUID EfiFirmwareVolumeTopFileGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1655 // Find the VTF file header location
1657 if (LocType
== FIRST_VTF
) {
1658 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1659 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1661 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1662 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1665 if (FileHeader
== NULL
) {
1666 return EFI_INVALID_PARAMETER
;
1672 memset (FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1673 memcpy (&FileHeader
->Name
, &EfiFirmwareVolumeTopFileGuid
, sizeof (EFI_GUID
));
1674 FileHeader
->Type
= EFI_FV_FILETYPE_RAW
;
1675 FileHeader
->Attributes
= FFS_ATTRIB_CHECKSUM
;
1678 // Now FileSize includes the EFI_FFS_FILE_HEADER
1680 FileHeader
->Size
[0] = (UINT8
) (TotalVtfSize
& 0x000000FF);
1681 FileHeader
->Size
[1] = (UINT8
) ((TotalVtfSize
& 0x0000FF00) >> 8);
1682 FileHeader
->Size
[2] = (UINT8
) ((TotalVtfSize
& 0x00FF0000) >> 16);
1685 // Fill in checksums and state, all three must be zero for the checksums.
1687 FileHeader
->IntegrityCheck
.Checksum
.Header
= 0;
1688 FileHeader
->IntegrityCheck
.Checksum
.File
= 0;
1689 FileHeader
->State
= 0;
1690 FileHeader
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1691 FileHeader
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) (FileHeader
+ 1), TotalVtfSize
- sizeof (EFI_FFS_FILE_HEADER
));
1692 FileHeader
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1698 ValidateAddressAndSize (
1699 IN UINT64 BaseAddress
,
1704 Routine Description:
1706 Update the Firmware Volume Buffer with requested buffer data
1710 BaseAddress - Base address for the Fw Volume.
1712 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1716 EFI_SUCCESS - The function completed successfully
1717 EFI_UNSUPPORTED - The input parameter is error
1721 if ((BaseAddress
>= 0) && (FwVolSize
> 0x40) && ((BaseAddress
+ FwVolSize
) % 8 == 0)) {
1725 return EFI_UNSUPPORTED
;
1729 UpdateIA32ResetVector (
1731 IN UINT64 FirstFwVSize
1735 Routine Description:
1737 Update the 16 byte IA32 Reset vector to maintain the compatibility
1741 FileName - Binary file name which contains the IA32 Reset vector info..
1742 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
1746 EFI_SUCCESS - The function completed successfully
1747 EFI_ABORTED - Invalid File Size
1748 EFI_INVALID_PARAMETER - Bad File Name
1749 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1754 UINT8
*LocalVtfBuffer
;
1759 if (!strcmp (FileName
, "")) {
1760 return EFI_INVALID_PARAMETER
;
1763 Fp
= fopen (FileName
, "rb");
1766 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1770 FileSize
= _filelength (fileno (Fp
));
1772 if (FileSize
> 16) {
1776 Buffer
= malloc (FileSize
);
1777 if (Buffer
== NULL
) {
1778 return EFI_OUT_OF_RESOURCES
;
1781 NumByteRead
= fread (Buffer
, sizeof (UINT8
), FileSize
, Fp
);
1783 LocalVtfBuffer
= (UINT8
*) Vtf1EndBuffer
- SIZE_IA32_RESET_VECT
;
1784 memcpy (LocalVtfBuffer
, Buffer
, FileSize
);
1802 Routine Description:
1804 This function cleans up any allocated buffer
1816 PARSED_VTF_INFO
*TempFileListPtr
;
1827 // Cleanup the buffer which was allocated to read the file names from FV.INF
1829 FileListPtr
= FileListHeadPtr
;
1830 while (FileListPtr
!= NULL
) {
1831 TempFileListPtr
= FileListPtr
->NextVtfInfo
;
1833 FileListPtr
= TempFileListPtr
;
1838 ProcessAndCreateVtf (
1843 Routine Description:
1845 This function process the link list created during INF file parsing
1846 and create component in VTF and updates its info in FIT table
1850 Size - Size of the Firmware Volume of which, this VTF belongs to.
1854 EFI_UNSUPPORTED - Unknown FIT type
1855 EFI_SUCCESS - The function completed successfully
1860 PARSED_VTF_INFO
*ParsedInfoPtr
;
1862 Status
= EFI_SUCCESS
;
1864 ParsedInfoPtr
= FileListHeadPtr
;
1866 while (ParsedInfoPtr
!= NULL
) {
1868 switch (ParsedInfoPtr
->CompType
) {
1870 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1872 case COMP_TYPE_FIT_HEADER
:
1873 //COMP_TYPE_FIT_HEADER 0x00
1874 Status
= CreateFitTableAndInitialize (ParsedInfoPtr
);
1878 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1880 case COMP_TYPE_FIT_PAL_A
:
1881 //COMP_TYPE_FIT_PAL_A 0x0F
1882 Status
= CreateAndUpdatePAL_A (ParsedInfoPtr
);
1885 // Based on VTF specification, once the PAL_A component has been written,
1886 // update the Firmware Volume info as FIT table. This will be utilized
1887 // to extract the Firmware Volume Start address where this VTF will be
1890 if (Status
== EFI_SUCCESS
) {
1891 UpdateFitEntryForFwVolume (Size
);
1895 case COMP_TYPE_FIT_FV_BOOT
:
1896 //COMP_TYPE_FIT_FV_BOOT 0x7E
1898 // Since FIT entry for Firmware Volume has been created and it is
1899 // located at (PAL_A start - 16 byte). So we will not process any
1900 // Firmware Volume related entry from INF file
1902 Status
= EFI_SUCCESS
;
1907 // Any other component type should be handled here. This will create the
1908 // image in specified VTF and create appropriate entry about this
1909 // component in FIT Entry.
1911 Status
= CreateAndUpdateComponent (ParsedInfoPtr
);
1912 if (EFI_ERROR (Status
)) {
1913 Error (NULL
, 0, 0002, "Error updating component", ParsedInfoPtr
->CompName
);
1919 ParsedInfoPtr
= ParsedInfoPtr
->NextVtfInfo
;
1926 IN UINT64 StartAddress1
,
1928 IN UINT64 StartAddress2
,
1934 Routine Description:
1936 This is the main function which will be called from application.
1940 StartAddress1 - The start address of the first VTF
1941 Size1 - The size of the first VTF
1942 StartAddress2 - The start address of the second VTF
1943 Size2 - The size of the second VTF
1944 fp - The pointer to BSF inf file
1948 EFI_OUT_OF_RESOURCES - Can not allocate memory
1949 The return value can be any of the values
1950 returned by the calls to following functions:
1951 GetVtfRelatedInfoFromInfFile
1953 UpdateIA32ResetVector
1962 Status
= EFI_UNSUPPORTED
;
1965 if (StartAddress2
== 0) {
1971 Fv1BaseAddress
= StartAddress1
;
1972 Fv1EndAddress
= Fv1BaseAddress
+ Size1
;
1973 if (Fv1EndAddress
!= 0x100000000ULL
|| Size1
< 0x100000) {
1974 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1975 if (Size1
< 0x100000) {
1976 Error (NULL
, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
1977 } else if (SecondVTF
!= TRUE
) {
1978 Error (NULL
, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
1981 return EFI_INVALID_PARAMETER
;
1985 // The image buffer for the First VTF
1987 Vtf1Buffer
= malloc ((UINTN
) Size1
);
1988 if (Vtf1Buffer
== NULL
) {
1989 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
1990 return EFI_OUT_OF_RESOURCES
;
1992 memset (Vtf1Buffer
, 0x00, (UINTN
) Size1
);
1993 Vtf1EndBuffer
= (UINT8
*) Vtf1Buffer
+ Size1
;
1994 Vtf1LastStartAddress
= Fv1EndAddress
| IPF_CACHE_BIT
;
1997 Fv2BaseAddress
= StartAddress2
;
1998 Fv2EndAddress
= Fv2BaseAddress
+ Size2
;
1999 if (Fv2EndAddress
!= StartAddress1
) {
2000 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
2001 if (SecondVTF
== TRUE
) {
2002 Error (NULL
, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
2003 Error (NULL
, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
2006 return EFI_INVALID_PARAMETER
;
2010 // The image buffer for the second VTF
2012 Vtf2Buffer
= malloc ((UINTN
) Size2
);
2013 if (Vtf2Buffer
== NULL
) {
2014 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2015 return EFI_OUT_OF_RESOURCES
;
2017 memset (Vtf2Buffer
, 0x00, (UINTN
) Size2
);
2018 Vtf2EndBuffer
= (UINT8
*) Vtf2Buffer
+ Size2
;
2019 Vtf2LastStartAddress
= Fv2EndAddress
| IPF_CACHE_BIT
;
2022 Status
= GetVtfRelatedInfoFromInfFile (VtfFP
);
2024 if (Status
!= EFI_SUCCESS
) {
2025 Error (NULL
, 0, 0003, "Error parsing file", "the input file.");
2030 Status
= ProcessAndCreateVtf (Size1
);
2031 if (Status
!= EFI_SUCCESS
) {
2036 if (SectionOptionFlag
) {
2037 Status
= UpdateIA32ResetVector (IA32BinFile
, Vtf1TotalSize
);
2038 if (Status
!= EFI_SUCCESS
) {
2045 // Re arrange the FIT Table for Ascending order of their FIT Type..
2050 // All components have been updated in FIT table. Now perform the FIT table
2051 // checksum. The following function will check if Checksum is required,
2052 // if yes, then it will perform the checksum otherwise not.
2054 CalculateFitTableChecksum ();
2057 // Write the FFS header
2059 Vtf1TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2060 Vtf1LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2062 Status
= UpdateFfsHeader (Vtf1TotalSize
, FIRST_VTF
);
2063 if (Status
!= EFI_SUCCESS
) {
2068 // Update the VTF buffer into specified VTF binary file
2070 Status
= WriteVtfBinary (OutFileName1
, Vtf1TotalSize
, FIRST_VTF
);
2073 Vtf2TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2074 Vtf2LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2075 Status
= UpdateFfsHeader (Vtf2TotalSize
, SECOND_VTF
);
2076 if (Status
!= EFI_SUCCESS
) {
2082 // Update the VTF buffer into specified VTF binary file
2084 Status
= WriteVtfBinary (OutFileName2
, Vtf2TotalSize
, SECOND_VTF
);
2093 PeimFixupInFitTable (
2094 IN UINT64 StartAddress
2098 Routine Description:
2100 This function is an entry point to fixup SAL-E entry point.
2104 StartAddress - StartAddress for PEIM.....
2108 EFI_SUCCESS - The function completed successfully
2109 EFI_ABORTED - Error Opening File
2110 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2116 UINT64
*StartAddressPtr
;
2120 StartAddressPtr
= malloc (sizeof (UINT64
));
2121 if (StartAddressPtr
== NULL
) {
2122 return EFI_OUT_OF_RESOURCES
;
2124 *StartAddressPtr
= StartAddress
;
2126 Fp
= fopen (OutFileName1
, "rb");
2129 Error (NULL
, 0, 0001, "Error opening file", OutFileName1
);
2130 if (StartAddressPtr
) {
2131 free (StartAddressPtr
);
2136 FirstFwVSize
= _filelength (fileno (Fp
));
2137 fseek (Fp
, (long) (FirstFwVSize
- (UINTN
) (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
)), SEEK_SET
);
2138 NumByte
= fwrite ((VOID
*) StartAddressPtr
, sizeof (UINT64
), 1, Fp
);
2144 if (StartAddressPtr
) {
2145 free (StartAddressPtr
);
2148 Status
= EFI_SUCCESS
;
2154 IN UINT64 BaseAddress
,
2155 IN CHAR8
*DestFileName
,
2156 IN CHAR8
*SourceFileName
,
2162 Routine Description:
2164 This function adds the SYM tokens in the source file to the destination file.
2165 The SYM tokens are updated to reflect the base address.
2169 BaseAddress - The base address for the new SYM tokens.
2170 DestFileName - The destination file.
2171 SourceFileName - The source file.
2172 FileSize - Size of bin file.
2176 EFI_SUCCESS - The function completed successfully.
2177 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2178 EFI_ABORTED - An error occurred.
2184 CHAR8 Buffer
[_MAX_PATH
];
2185 CHAR8 Type
[_MAX_PATH
];
2186 CHAR8 Address
[_MAX_PATH
];
2187 CHAR8 Section
[_MAX_PATH
];
2188 CHAR8 Token
[_MAX_PATH
];
2189 CHAR8 BaseToken
[_MAX_PATH
];
2190 UINT64 TokenAddress
;
2194 // Verify input parameters.
2196 if (BaseAddress
== 0 || DestFileName
== NULL
|| SourceFileName
== NULL
) {
2197 return EFI_INVALID_PARAMETER
;
2201 // Open the source file
2203 SourceFile
= fopen (SourceFileName
, "r");
2204 if (SourceFile
== NULL
) {
2207 // SYM files are not required.
2213 // Use the file name minus extension as the base for tokens
2215 strcpy (BaseToken
, SourceFileName
);
2216 strtok (BaseToken
, ". \t\n");
2217 strcat (BaseToken
, "__");
2220 // Open the destination file
2222 DestFile
= fopen (DestFileName
, "a+");
2223 if (DestFile
== NULL
) {
2224 fclose (SourceFile
);
2225 Error (NULL
, 0, 0001, "Error opening file", DestFileName
);
2230 // If this is the beginning of the output file, write the symbol format info.
2232 if (fseek (DestFile
, 0, SEEK_END
) != 0) {
2233 fclose (SourceFile
);
2235 Error (NULL
, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2239 StartLocation
= ftell (DestFile
);
2241 if (StartLocation
== 0) {
2242 fprintf (DestFile
, "TEXTSYM format | V1.0\n");
2243 } else if (StartLocation
== -1) {
2244 fclose (SourceFile
);
2246 Error (NULL
, 0, 2000, "Invalid parameter", "StartLocation error");
2251 // Read the first line
2253 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
2258 // Make sure it matches the expected sym format
2260 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
2261 fclose (SourceFile
);
2263 Error (NULL
, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2270 while (feof (SourceFile
) == 0) {
2275 if (fscanf (SourceFile
, "%s | %s | %s | %s\n", Type
, Address
, Section
, Token
) == 4) {
2278 // Get the token address
2280 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
2281 if (TokenAddress
> FileSize
) {
2283 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2289 // Add the base address, the size of the FFS file header and the size of the peim header.
2291 TokenAddress
+= BaseAddress
&~IPF_CACHE_BIT
;
2293 fprintf (DestFile
, "%s | %016llX | ", Type
, (unsigned long long) TokenAddress
);
2294 fprintf (DestFile
, "%s | %s\n %s\n", Section
, Token
, BaseToken
);
2298 fclose (SourceFile
);
2304 CalculateFitTableChecksum (
2309 Routine Description:
2311 This function will perform byte checksum on the FIT table, if the the checksum required
2312 field is set to CheckSum required. If the checksum is not required then checksum byte
2313 will have value as 0;.
2321 Status - Value returned by call to CalculateChecksum8 ()
2322 EFI_SUCCESS - The function completed successfully
2326 FIT_TABLE
*TmpFitPtr
;
2328 UINT64 FitTableAddOffset
;
2329 UINTN RelativeAddress
;
2333 // Read the Fit Table address from Itanium-based address map.
2335 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
2338 // Translate this Itanium-based address in terms of local buffer address which
2339 // contains the image for Boot Strapped File
2341 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
2342 FitTableAdd
= *(UINTN
*) RelativeAddress
;
2344 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
2346 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
2348 Size
= TmpFitPtr
->CompSize
* 16;
2350 if ((TmpFitPtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2351 TmpFitPtr
->CheckSum
= 0;
2352 TmpFitPtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) TmpFitPtr
, Size
);
2354 TmpFitPtr
->CheckSum
= 0;
2366 Routine Description:
2368 Displays the standard utility information to SDTOUT
2380 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
2389 Routine Description:
2391 Displays the utility usage syntax to STDOUT
2406 fprintf (stdout
, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME
);
2409 // Copyright declaration
2411 fprintf (stdout
, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n");
2415 fprintf (stdout
, "Options:\n");
2416 fprintf (stdout
, " -f Input_file, --filename Input_file\n\
2417 Input_file is name of the BS Image INF file\n");
2418 fprintf (stdout
, " -r BaseAddress, --baseaddr BaseAddress\n\
2419 BaseAddress is the starting address of Firmware Volume\n\
2420 where Boot Strapped Image will reside.\n");
2421 fprintf (stdout
, " -s FwVolumeSize, --size FwVolumeSize\n\
2422 FwVolumeSize is the size of Firmware Volume.\n");
2423 fprintf (stdout
, " -o FileName, --output FileName\n\
2424 File will be created to store the ouput content.\n");
2425 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
2426 fprintf (stdout
, " --version Show program's version number and exit.\n");
2427 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
2428 fprintf (stdout
, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
2429 fprintf (stdout
, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
2439 Routine Description:
2441 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2442 part of firmware volume image.
2446 argc - The count of the parameters
2447 argv - The parameters
2452 0 - No error conditions detected.
2453 1 - One or more of the input parameters is invalid.
2454 2 - A resource required by the utility was unavailable.
2455 - Most commonly this will be memory allocation or file creation.
2456 3 - GenFvImage.dll could not be loaded.
2457 4 - Error executing the GenFvImage dll.
2458 5 - Now this tool does not support the IA32 platform
2463 UINT64 StartAddress1
;
2464 UINT64 StartAddress2
;
2467 BOOLEAN FirstRoundO
;
2468 BOOLEAN FirstRoundB
;
2469 BOOLEAN FirstRoundS
;
2474 SetUtilityName (UTILITY_NAME
);
2477 // Initialize variables
2487 OutFileName1
= NULL
;
2488 OutFileName2
= NULL
;
2493 // Verify the correct number of arguments
2500 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
2505 if ((strcmp(argv
[1], "--version") == 0)) {
2511 // Parse the command line arguments
2513 for (Index
= 1; Index
< argc
; Index
+= 2) {
2514 if ((stricmp (argv
[Index
], "-o") == 0) || (stricmp (argv
[Index
], "--output") == 0)) {
2515 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2516 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
2520 // Get the output file name
2525 // It's the first output file name
2527 OutFileName1
= (CHAR8
*)argv
[Index
+1];
2528 FirstRoundO
= FALSE
;
2531 //It's the second output file name
2533 OutFileName2
= (CHAR8
*)argv
[Index
+1];
2538 if ((stricmp (argv
[Index
], "-f") == 0) || (stricmp (argv
[Index
], "--filename") == 0)) {
2539 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2540 Error (NULL
, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
2544 // Get the input VTF file name
2546 VtfFileName
= argv
[Index
+1];
2547 VtfFP
= fopen(VtfFileName
, "rb");
2548 if (VtfFP
== NULL
) {
2549 Error (NULL
, 0, 0001, "Error opening file", VtfFileName
);
2555 if ((stricmp (argv
[Index
], "-r") == 0) || (stricmp (argv
[Index
], "--baseaddr") == 0)) {
2557 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress1
);
2558 FirstRoundB
= FALSE
;
2560 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress2
);
2562 if (Status
!= EFI_SUCCESS
) {
2563 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv
[Index
+ 1]);
2569 if ((stricmp (argv
[Index
], "-s") == 0) || (stricmp (argv
[Index
], "--size") == 0)) {
2571 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize1
);
2572 FirstRoundS
= FALSE
;
2574 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize2
);
2578 if (Status
!= EFI_SUCCESS
) {
2579 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv
[Index
+ 1]);
2585 if ((stricmp (argv
[Index
], "-v") == 0) || (stricmp (argv
[Index
], "--verbose") == 0)) {
2591 if ((stricmp (argv
[Index
], "-q") == 0) || (stricmp (argv
[Index
], "--quiet") == 0)) {
2597 if ((stricmp (argv
[Index
], "-d") == 0) || (stricmp (argv
[Index
], "--debug") == 0)) {
2599 // debug level specified
2601 Status
= AsciiStringToUint64(argv
[Index
+ 1], FALSE
, &DebugLevel
);
2602 if (EFI_ERROR (Status
)) {
2603 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[Index
], argv
[Index
+ 1]);
2606 if (DebugLevel
> 9) {
2607 Error (NULL
, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv
[Index
+ 1]);
2610 if((DebugLevel
<= 9) &&(DebugLevel
>= 5)) {
2618 Error (NULL
, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv
[Index
]);
2622 if (VtfFP
== NULL
) {
2623 Error (NULL
, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2628 Error (NULL
, 0, 2000, "Invalid parameter", "No FV base address is specified");
2633 Error (NULL
, 0, 2000, "Invalid parameter", "No FV Size is specified");
2637 // All Parameters has been parsed, now set the message print level
2641 } else if (VerboseMode
) {
2643 } else if (DebugMode
) {
2644 SetPrintLevel(DebugLevel
);
2648 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
2651 if (VTF_OUTPUT
== FALSE
) {
2652 if (SecondVTF
== TRUE
) {
2653 OutFileName1
= VTF_OUTPUT_FILE1
;
2654 OutFileName2
= VTF_OUTPUT_FILE2
;
2656 OutFileName1
= VTF_OUTPUT_FILE1
;
2658 SymFileName
= VTF_SYM_FILE
;
2660 INTN OutFileNameLen
= strlen(OutFileName1
);
2663 for (Index
= OutFileNameLen
; Index
> 0; --Index
) {
2664 if (OutFileName1
[Index
] == '/' || OutFileName1
[Index
] == '\\') {
2669 SymFileName
= VTF_SYM_FILE
;
2671 INTN SymFileNameLen
= Index
+ 1 + strlen(VTF_SYM_FILE
);
2672 SymFileName
= malloc(SymFileNameLen
+ 1);
2673 memcpy(SymFileName
, OutFileName1
, Index
+ 1);
2674 memcpy(SymFileName
+ Index
+ 1, VTF_SYM_FILE
, strlen(VTF_SYM_FILE
));
2675 SymFileName
[SymFileNameLen
] = '\0';
2678 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, SymFileName
, NULL
);
2683 // Call the GenVtfImage
2686 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Start to generate the VTF image\n", NULL
);
2688 Status
= GenerateVtfImage (StartAddress1
, FwVolSize1
, StartAddress2
, FwVolSize2
, VtfFP
);
2690 if (EFI_ERROR (Status
)) {
2693 case EFI_INVALID_PARAMETER
:
2694 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2698 Error (NULL
, 0, 3000, "Invalid", "Error detected while creating the file image.");
2701 case EFI_OUT_OF_RESOURCES
:
2702 Error (NULL
, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2705 case EFI_VOLUME_CORRUPTED
:
2706 Error (NULL
, 0, 3000, "Invalid", "No base address was specified.");
2710 Error (NULL
, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status
);
2715 if (VtfFP
!= NULL
) {
2720 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "VTF image generated successful\n", NULL
);
2724 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2726 return GetUtilityStatus();