3 Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 This file contains functions required to generate a boot strap file (BSF)
20 also known as the Volume Top File (VTF)
28 #include <Common/UefiBaseTypes.h>
30 #include <Guid/PiFirmwareFileSystem.h>
31 #include "CommonLib.h"
32 #include "EfiUtilityMsgs.h"
37 UINTN SectionOptionFlag
= 0;
38 UINTN SectionCompFlag
= 0;
43 BOOLEAN QuietMode
= FALSE
;
45 BOOLEAN VTF_OUTPUT
= FALSE
;
53 PARSED_VTF_INFO
*FileListPtr
;
54 PARSED_VTF_INFO
*FileListHeadPtr
;
61 UINTN ValidLineNum
= 0;
62 UINTN ValidFFDFileListNum
= 0;
65 // Section Description and their number of occurences in *.INF file
68 UINTN SectionOptionNum
= 0;
71 // Global flag which will check for VTF Present, if yes then will be used
72 // to decide about adding FFS header to pad data
74 BOOLEAN VTFPresent
= FALSE
;
75 BOOLEAN SecondVTF
= FALSE
;
78 // Address related information
80 UINT64 Fv1BaseAddress
= 0;
81 UINT64 Fv2BaseAddress
= 0;
82 UINT64 Fv1EndAddress
= 0;
83 UINT64 Fv2EndAddress
= 0;
84 UINT32 Vtf1TotalSize
= SIZE_TO_OFFSET_PAL_A_END
;
85 UINT64 Vtf1LastStartAddress
= 0;
86 UINT32 Vtf2TotalSize
= 0;
87 UINT64 Vtf2LastStartAddress
= 0;
89 UINT32 BufferToTop
= 0;
92 // IA32 Reset Vector Bin name
94 CHAR8 IA32BinFile
[FILE_NAME_SIZE
];
97 // Function Implementations
102 IN OUT UINT8
*MajorVer
,
103 IN OUT UINT8
*MinorVer
108 This function split version to major version and minor version
112 Str - String representing in form XX.XX
113 MajorVer - The major version
114 MinorVer - The minor version
118 EFI_SUCCESS - The function completed successfully.
122 CHAR8 TemStr
[5] = "0000";
130 if (strstr (Str
, ".") != NULL
) {
138 Length
= strlen(Str
);
140 strncpy (TemStr
+ 4 - Length
, Str
, Length
);
142 strncpy (TemStr
, Str
+ Length
- 4, 4);
153 *MajorVer
= (UINT8
) Major
;
154 *MinorVer
= (UINT8
) Minor
;
165 This function cleans up the line by removing all whitespace and
170 Line - The pointer of the string
178 CHAR8 TmpLine
[FILE_NAME_SIZE
];
185 // Change '#' to '//' for Comment style
187 if (((Ptr0
= strchr (Line
, '#')) != NULL
) || ((Ptr0
= strstr (Line
, "//")) != NULL
)) {
188 Line
[Ptr0
- Line
] = 0;
192 // Initialize counters
197 while ((Char
= Line
[Index
]) != 0) {
198 if ((Char
!= ' ') && (Char
!= '\t') && (Char
!= '\n') && (Char
!= '\r')) {
199 TmpLine
[Index2
++] = Char
;
205 strcpy (Line
, TmpLine
);
216 This function calculated number of valid lines in a input file.
220 Fp - Pointer to a file handle which has been opened.
228 CHAR8 Buff
[FILE_NAME_SIZE
];
229 while (fgets(Buff
, sizeof (Buff
), Fp
)) {
246 This function parses the input file and tokenize the string
250 Fp - Pointer to a file handle which has been opened.
259 CHAR8 Buff
[FILE_NAME_SIZE
+ 1];
260 CHAR8 Delimit
[] = "=";
262 Buff
[FILE_NAME_SIZE
] = '\0';
265 while (fgets (Buff
, FILE_NAME_SIZE
, Fp
) != NULL
) {
270 Token
= strtok (Buff
, Delimit
);
271 while (Token
!= NULL
) {
272 strcpy (*TokenStr
, Token
);
274 Token
= strtok (NULL
, Delimit
);
288 This function initializes the relevant global variable which is being
289 used to store the information retrieved from INF file. This also initializes
298 EFI_SUCCESS - The function completed successfully
299 EFI_OUT_OF_RESOURCES - Malloc failed.
304 FileListPtr
= malloc (sizeof (PARSED_VTF_INFO
));
306 if (FileListPtr
== NULL
) {
307 return EFI_OUT_OF_RESOURCES
;
310 FileListHeadPtr
= FileListPtr
;
311 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
312 FileListPtr
->NextVtfInfo
= NULL
;
314 remove (SymFileName
);
319 ParseAndUpdateComponents (
320 IN PARSED_VTF_INFO
*VtfInfo
326 This function initializes the relevant global variable which is being
327 used to store the information retrieved from INF file.
331 VtfInfo - A pointer to the VTF Info Structure
342 while (*TokenStr
!= NULL
&& (strnicmp (*TokenStr
, "COMP_NAME", 9) != 0)) {
344 if (strnicmp (*TokenStr
, "COMP_LOC", 8) == 0) {
346 if (strnicmp (*TokenStr
, "F", 1) == 0) {
347 VtfInfo
->LocationType
= FIRST_VTF
;
348 } else if (strnicmp (*TokenStr
, "S", 1) == 0) {
349 VtfInfo
->LocationType
= SECOND_VTF
;
351 VtfInfo
->LocationType
= NONE
;
353 } else if (strnicmp (*TokenStr
, "COMP_TYPE", 9) == 0) {
355 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
356 Error (NULL
, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr
);
360 VtfInfo
->CompType
= (UINT8
) StringValue
;
361 } else if (strnicmp (*TokenStr
, "COMP_VER", 8) == 0) {
363 if (strnicmp (*TokenStr
, "-", 1) == 0) {
364 VtfInfo
->VersionPresent
= FALSE
;
365 VtfInfo
->MajorVer
= 0;
366 VtfInfo
->MinorVer
= 0;
368 VtfInfo
->VersionPresent
= TRUE
;
369 ConvertVersionInfo (*TokenStr
, &VtfInfo
->MajorVer
, &VtfInfo
->MinorVer
);
371 } else if (strnicmp (*TokenStr
, "COMP_BIN", 8) == 0) {
373 strcpy (VtfInfo
->CompBinName
, *TokenStr
);
374 } else if (strnicmp (*TokenStr
, "COMP_SYM", 8) == 0) {
376 strcpy (VtfInfo
->CompSymName
, *TokenStr
);
377 } else if (strnicmp (*TokenStr
, "COMP_SIZE", 9) == 0) {
379 if (strnicmp (*TokenStr
, "-", 1) == 0) {
380 VtfInfo
->PreferredSize
= FALSE
;
381 VtfInfo
->CompSize
= 0;
383 VtfInfo
->PreferredSize
= TRUE
;
384 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
385 Error (NULL
, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr
);
389 VtfInfo
->CompSize
= (UINTN
) StringValue
;
392 } else if (strnicmp (*TokenStr
, "COMP_CS", 7) == 0) {
394 if (strnicmp (*TokenStr
, "1", 1) == 0) {
395 VtfInfo
->CheckSumRequired
= 1;
396 } else if (strnicmp (*TokenStr
, "0", 1) == 0) {
397 VtfInfo
->CheckSumRequired
= 0;
399 Error (NULL
, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
404 if (*TokenStr
== NULL
) {
411 InitializeInFileInfo (
418 This function intializes the relevant global variable which is being
419 used to store the information retrieved from INF file.
432 SectionOptionFlag
= 0;
434 TokenStr
= OrgStrTokPtr
;
436 while (*TokenStr
!= NULL
) {
437 if (strnicmp (*TokenStr
, "[OPTIONS]", 9) == 0) {
438 SectionOptionFlag
= 1;
442 if (strnicmp (*TokenStr
, "[COMPONENTS]", 12) == 0) {
443 if (FileListPtr
== NULL
) {
444 FileListPtr
= FileListHeadPtr
;
448 SectionOptionFlag
= 0;
452 if (SectionOptionFlag
) {
453 if (stricmp (*TokenStr
, "IA32_RST_BIN") == 0) {
455 strcpy (IA32BinFile
, *TokenStr
);
459 if (SectionCompFlag
) {
460 if (stricmp (*TokenStr
, "COMP_NAME") == 0) {
462 strcpy (FileListPtr
->CompName
, *TokenStr
);
464 ParseAndUpdateComponents (FileListPtr
);
467 if (*TokenStr
!= NULL
) {
468 FileListPtr
->NextVtfInfo
= malloc (sizeof (PARSED_VTF_INFO
));
469 if (FileListPtr
->NextVtfInfo
== NULL
) {
470 Error (NULL
, 0, 4003, "Resource", "Out of memory resources.", NULL
);
473 FileListPtr
= FileListPtr
->NextVtfInfo
;
474 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
475 FileListPtr
->NextVtfInfo
= NULL
;
487 GetVtfRelatedInfoFromInfFile (
494 This function reads the input file, parse it and create a list of tokens
495 which is parsed and used, to intialize the data related to VTF
499 FileName - FileName which needed to be read to parse data
503 EFI_ABORTED - Error in opening file
504 EFI_INVALID_PARAMETER - File doesn't contain any valid information
505 EFI_OUT_OF_RESOURCES - Malloc Failed
506 EFI_SUCCESS - The function completed successfully
515 Status
= EFI_SUCCESS
;
518 Error (NULL
, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
524 if (ValidLineNum
== 0) {
525 Error (NULL
, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
526 return EFI_INVALID_PARAMETER
;
529 TokenStr
= (CHAR8
**) malloc (sizeof (UINTN
) * (2 * ValidLineNum
+ 1));
531 if (TokenStr
== NULL
) {
532 return EFI_OUT_OF_RESOURCES
;
535 memset (TokenStr
, 0, (sizeof (UINTN
) * (2 * ValidLineNum
+ 1)));
536 OrgStrTokPtr
= TokenStr
;
538 for (Index
= 0; Index
< (2 * ValidLineNum
); Index
++) {
539 *TokenStr
= (CHAR8
*)malloc (sizeof (CHAR8
) * FILE_NAME_SIZE
);
541 if (*TokenStr
== NULL
) {
542 Status
= EFI_OUT_OF_RESOURCES
;
546 memset (*TokenStr
, 0, FILE_NAME_SIZE
);
550 TokenStr
= OrgStrTokPtr
;
551 fseek (Fp
, 0L, SEEK_SET
);
553 Status
= InitializeComps ();
555 if (Status
!= EFI_SUCCESS
) {
559 Status
= ParseInputFile (Fp
);
560 if (Status
!= EFI_SUCCESS
) {
564 InitializeInFileInfo ();
568 for (Index1
= 0; Index1
< Index
; Index1
++) {
569 free (OrgStrTokPtr
[Index1
]);
578 GetRelativeAddressInVtfBuffer (
580 IN OUT UINTN
*RelativeAddress
,
587 This function checks for the address alignmnet for specified data boundary. In
588 case the address is not aligned, it returns FALSE and the amount of data in
589 terms of byte needed to adjust to get the boundary alignmnet. If data is
590 aligned, TRUE will be returned.
594 Address - The address of the flash map space
595 RelativeAddress - The relative address of the Buffer
596 LocType - The type of the VTF
607 if (LocType
== FIRST_VTF
) {
608 LocalBuff
= (UINT8
*) Vtf1EndBuffer
;
609 TempAddress
= Fv1EndAddress
- Address
;
610 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
612 LocalBuff
= (UINT8
*) Vtf2EndBuffer
;
613 TempAddress
= Fv2EndAddress
- Address
;
614 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
619 GetComponentVersionInfo (
620 IN OUT PARSED_VTF_INFO
*VtfInfo
,
626 This function will extract the version information from File
630 VtfInfo - A Pointer to the VTF Info Structure
631 Buffer - A Pointer to type UINT8
635 EFI_SUCCESS - The function completed successfully
636 EFI_INVALID_PARAMETER - The parameter is invalid
643 switch (VtfInfo
->CompType
) {
645 case COMP_TYPE_FIT_PAL_A
:
646 case COMP_TYPE_FIT_PAL_B
:
647 memcpy (&VersionInfo
, (Buffer
+ 8), sizeof (UINT16
));
648 VtfInfo
->MajorVer
= (UINT8
) ((VersionInfo
& 0xFF00) >> 8);
649 VtfInfo
->MinorVer
= (UINT8
) (VersionInfo
& 0x00FF);
650 Status
= EFI_SUCCESS
;
654 Status
= EFI_INVALID_PARAMETER
;
662 CheckAddressAlignment (
664 IN UINT64 AlignmentData
,
665 IN OUT UINT64
*AlignAdjustByte
671 This function checks for the address alignmnet for specified data boundary. In
672 case the address is not aligned, it returns FALSE and the amount of data in
673 terms of byte needed to adjust to get the boundary alignmnet. If data is
674 aligned, TRUE will be returned.
678 Address - Pointer to buffer containing byte data of component.
679 AlignmentData - DataSize for which address needed to be aligned
680 AlignAdjustByte - Number of bytes needed to adjust alignment.
684 TRUE - Address is aligned to specific data size boundary
685 FALSE - Address in not aligned to specified data size boundary
686 - Add/Subtract AlignAdjustByte to aling the address.
691 // Check if the assigned address is on address boundary. If not, it will
692 // return the remaining byte required to adjust the address for specified
695 *AlignAdjustByte
= (Address
% AlignmentData
);
697 if (*AlignAdjustByte
== 0) {
705 GetFitTableStartAddress (
706 IN OUT FIT_TABLE
**FitTable
712 Get the FIT table start address in VTF Buffer
716 FitTable - Pointer to available fit table where new component can be added
720 EFI_SUCCESS - The function completed successfully
725 UINT64 FitTableAddOffset
;
726 UINTN RelativeAddress
;
729 // Read the Fit Table address from Itanium-based address map.
731 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
734 // Translate this Itanium-based address in terms of local buffer address which
735 // contains the image for Boot Strapped File. The relative address will be
736 // the address of fit table VTF buffer.
738 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
739 FitTableAdd
= *(UINTN
*) RelativeAddress
;
742 // The FitTableAdd is the extracted Itanium based address pointing to FIT
743 // table. The relative address will return its actual location in VTF
746 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
748 *FitTable
= (FIT_TABLE
*) RelativeAddress
;
754 GetNextAvailableFitPtr (
755 IN FIT_TABLE
**FitPtr
761 Get the FIT table address and locate the free space in fit where we can add
762 new component. In this process, this function locates the fit table using
763 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
764 and locate the available location in FIT table to be used by new components.
765 If there are any Fit table which areg not being used contains ComponentType
766 field as 0x7F. If needed we can change this and spec this out.
770 FitPtr - Pointer to available fit table where new component can be added
774 EFI_SUCCESS - The function completed successfully
778 FIT_TABLE
*TmpFitPtr
;
780 UINT64 FitTableAddOffset
;
782 UINTN NumFitComponents
;
783 UINTN RelativeAddress
;
786 // Read the Fit Table address from Itanium-based address map.
788 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
791 // Translate this Itanium-based address in terms of local buffer address which
792 // contains the image for Boot Strapped File. The relative address will be
793 // the address of fit table VTF buffer.
795 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
796 FitTableAdd
= *(UINTN
*) RelativeAddress
;
799 // The FitTableAdd is the extracted Itanium based address pointing to FIT
800 // table. The relative address will return its actual location in VTF
803 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
805 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
806 NumFitComponents
= TmpFitPtr
->CompSize
;
808 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
809 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_UNUSED
) {
829 This function is used by qsort to sort the FIT table based upon Component
830 Type in their incresing order.
834 Arg1 - Pointer to Arg1
835 Arg2 - Pointer to Arg2
843 if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) > (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
845 } else if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) < (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
860 This function is used by qsort to sort the FIT table based upon Component
861 Type in their incresing order.
874 FIT_TABLE
*TmpFitPtr
;
875 UINTN NumFitComponents
;
878 GetFitTableStartAddress (&FitTable
);
879 TmpFitPtr
= FitTable
;
880 NumFitComponents
= 0;
881 for (Index
= 0; Index
< FitTable
->CompSize
; Index
++) {
882 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) != COMP_TYPE_FIT_UNUSED
) {
883 NumFitComponents
+= 1;
887 qsort ((VOID
*) FitTable
, NumFitComponents
, sizeof (FIT_TABLE
), CompareItems
);
891 UpdateFitEntryForFwVolume (
898 This function updates the information about Firmware Volume in FIT TABLE.
899 This FIT table has to be immediately below the PAL_A Start and it contains
900 component type and address information. Other information can't be
901 created this time so we would need to fix it up..
906 Size - Firmware Volume Size
914 FIT_TABLE
*CompFitPtr
;
915 UINTN RelativeAddress
;
918 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
920 Vtf1LastStartAddress
-= 0x10;
921 Vtf1TotalSize
+= 0x10;
923 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
925 CompFitPtr
= (FIT_TABLE
*) RelativeAddress
;
926 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
929 // Since we don't have any information about its location in Firmware Volume,
930 // initialize address to 0. This will be updated once Firmware Volume is
931 // being build and its current address will be fixed in FIT table. Currently
932 // we haven't implemented it so far and working on architectural clarafication
935 // Firmware Volume Size in 16 byte block
937 CompFitPtr
->CompSize
= ((UINT32
) Size
) / 16;
940 // Since Firmware Volume does not exist by the time we create this FIT info
941 // this should be fixedup from Firmware Volume creation tool. We haven't
942 // worked out a method so far.
944 CompFitPtr
->CompVersion
= MAKE_VERSION (0, 0);
947 // Since we don't have any info about this file, we are making sure that
948 // checksum is not needed.
950 CompFitPtr
->CvAndType
= CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT
);
953 // Since non VTF component will reside outside the VTF, we will not have its
954 // binary image while creating VTF, hence we will not perform checksum at
955 // this time. Once Firmware Volume is being created which will contain this
956 // VTF, it will fix the FIT table for all the non VTF component and hence
959 CompFitPtr
->CheckSum
= 0;
963 UpdateFitEntryForNonVTFComp (
964 IN PARSED_VTF_INFO
*VtfInfo
970 This function updates the information about non VTF component in FIT TABLE.
971 Since non VTF componets binaries are not part of VTF binary, we would still
972 be required to update its location information in Firmware Volume, inside
977 VtfInfo - Pointer to VTF Info Structure
981 EFI_ABORTED - The function fails to update the component in FIT
982 EFI_SUCCESS - The function completed successfully
986 FIT_TABLE
*CompFitPtr
;
989 // Scan the FIT table for available space
991 GetNextAvailableFitPtr (&CompFitPtr
);
992 if (CompFitPtr
== NULL
) {
993 Error (NULL
, 0, 5003, "Invalid", "Can't update this component in FIT");
998 // Since we don't have any information about its location in Firmware Volume,
999 // initialize address to 0. This will be updated once Firmware Volume is
1000 // being build and its current address will be fixed in FIT table
1002 CompFitPtr
->CompAddress
= 0;
1003 CompFitPtr
->CompSize
= VtfInfo
->CompSize
;
1004 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1005 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1008 // Since non VTF component will reside outside the VTF, we will not have its
1009 // binary image while creating VTF, hence we will not perform checksum at
1010 // this time. Once Firmware Volume is being created which will contain this
1011 // VTF, it will fix the FIT table for all the non VTF component and hence
1014 CompFitPtr
->CheckSum
= 0;
1017 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
1018 // address of Firmware Volume in which this VTF will be attached.
1020 if ((CompFitPtr
->CvAndType
& 0x7F) == COMP_TYPE_FIT_FV_BOOT
) {
1021 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
1029 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
1030 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
1031 // CORE moves in Firmware Volume, we would need to modify this function to be
1032 // used with a API which will detect PEICORE component while building Firmware
1033 // Volume and update its entry in FIT table as well as in Itanium address space
1034 // as per Intel?Itanium(TM) SAL address space
1038 IN PARSED_VTF_INFO
*VtfInfo
,
1039 IN UINT64
*CompStartAddress
1043 Routine Description:
1045 This function updated the architectural entry point in IPF, SALE_ENTRY.
1049 VtfInfo - Pointer to VTF Info Structure
1050 CompStartAddress - Pointer to Component Start Address
1054 EFI_INVALID_PARAMETER - The parameter is invalid
1055 EFI_SUCCESS - The function completed successfully
1059 UINTN RelativeAddress
;
1064 CHAR8 Buff
[FILE_NAME_SIZE
];
1067 CHAR8 OffsetStr
[30];
1073 Fp
= fopen (VtfInfo
->CompSymName
, "rb");
1076 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompSymName
);
1077 return EFI_INVALID_PARAMETER
;
1080 while (fgets (Buff
, sizeof (Buff
), Fp
) != NULL
) {
1083 "%s %s %s %s %s %s %s",
1092 if (strnicmp (Token
, "SALE_ENTRY", 10) == 0) {
1097 Offset
= strtoul (OffsetStr
, NULL
, 16);
1099 *CompStartAddress
+= Offset
;
1100 SalEntryAdd
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
);
1102 GetRelativeAddressInVtfBuffer (SalEntryAdd
, &RelativeAddress
, FIRST_VTF
);
1104 memcpy ((VOID
*) RelativeAddress
, (VOID
*) CompStartAddress
, sizeof (UINT64
));
1114 CreateAndUpdateComponent (
1115 IN PARSED_VTF_INFO
*VtfInfo
1119 Routine Description:
1121 This function reads the binary file for each components and update them
1122 in VTF Buffer as well as in FIT table. If the component is located in non
1123 VTF area, only the FIT table address will be updated
1127 VtfInfo - Pointer to Parsed Info
1131 EFI_SUCCESS - The function completed successful
1132 EFI_ABORTED - Aborted due to one of the many reasons like:
1133 (a) Component Size greater than the specified size.
1134 (b) Error opening files.
1136 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1137 EFI_OUT_OF_RESOURCES Memory allocation failure.
1142 UINT64 CompStartAddress
;
1145 UINT64 NumAdjustByte
;
1148 FIT_TABLE
*CompFitPtr
;
1151 if (VtfInfo
->LocationType
== NONE
) {
1152 UpdateFitEntryForNonVTFComp (VtfInfo
);
1156 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1159 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1163 FileSize
= _filelength (fileno (Fp
));
1164 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1167 // BUGBUG: Satish to correct
1169 FileSize
-= SIZE_OF_PAL_HEADER
;
1172 if (VtfInfo
->PreferredSize
) {
1173 if (FileSize
> VtfInfo
->CompSize
) {
1174 Error (NULL
, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1178 FileSize
= VtfInfo
->CompSize
;
1181 Buffer
= malloc ((UINTN
) FileSize
);
1182 if (Buffer
== NULL
) {
1183 return EFI_OUT_OF_RESOURCES
;
1185 memset (Buffer
, 0, (UINTN
) FileSize
);
1187 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1190 // Read first 64 bytes of PAL header and use it to find version info
1192 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1195 // PAL header contains the version info. Currently, we will use the header
1196 // to read version info and then discard.
1198 if (!VtfInfo
->VersionPresent
) {
1199 GetComponentVersionInfo (VtfInfo
, Buffer
);
1203 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1207 // If it is non PAL_B component, pass the entire buffer to get the version
1208 // info and implement any specific case inside GetComponentVersionInfo.
1210 if (VtfInfo
->CompType
!= COMP_TYPE_FIT_PAL_B
) {
1211 if (!VtfInfo
->VersionPresent
) {
1212 GetComponentVersionInfo (VtfInfo
, Buffer
);
1216 if (VtfInfo
->LocationType
== SECOND_VTF
) {
1218 CompStartAddress
= (Vtf2LastStartAddress
- FileSize
);
1220 CompStartAddress
= (Vtf1LastStartAddress
- FileSize
);
1223 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) {
1224 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 32 * 1024, &NumAdjustByte
);
1226 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 8, &NumAdjustByte
);
1230 CompStartAddress
-= NumAdjustByte
;
1233 if (VtfInfo
->LocationType
== SECOND_VTF
&& SecondVTF
== TRUE
) {
1234 Vtf2LastStartAddress
= CompStartAddress
;
1235 Vtf2TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1236 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, SECOND_VTF
);
1237 } else if (VtfInfo
->LocationType
== FIRST_VTF
) {
1238 Vtf1LastStartAddress
= CompStartAddress
;
1239 Vtf1TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1240 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1242 Error (NULL
, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
1243 return EFI_INVALID_PARAMETER
;
1246 if (EFI_ERROR (Status
)) {
1250 GetNextAvailableFitPtr (&CompFitPtr
);
1252 CompFitPtr
->CompAddress
= CompStartAddress
| IPF_CACHE_BIT
;
1253 if ((FileSize
% 16) != 0) {
1254 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1255 return EFI_INVALID_PARAMETER
;
1257 //assert ((FileSize % 16) == 0);
1258 CompFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1259 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1260 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1261 if (VtfInfo
->CheckSumRequired
) {
1262 CompFitPtr
->CheckSum
= 0;
1263 CompFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1274 // Update the SYM file for this component based on it's start address.
1276 Status
= UpdateSymFile (CompStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1277 if (EFI_ERROR (Status
)) {
1280 // At this time, SYM files are not required, so continue on error.
1284 // !!!!!!!!!!!!!!!!!!!!!
1286 // This part of the code is a temporary line since PEICORE is going to be inside
1287 // VTF till we work out how to determine the SALE_ENTRY through it. We will need
1288 // to clarify so many related questions
1289 // !!!!!!!!!!!!!!!!!!!!!!!
1291 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PEICORE
) {
1292 Status
= UpdateEntryPoint (VtfInfo
, &CompStartAddress
);
1299 CreateAndUpdatePAL_A (
1300 IN PARSED_VTF_INFO
*VtfInfo
1304 Routine Description:
1306 This function reads the binary file for each components and update them
1307 in VTF Buffer as well as FIT table
1311 VtfInfo - Pointer to Parsed Info
1315 EFI_ABORTED - Due to one of the following reasons:
1316 (a)Error Opening File
1317 (b)The PAL_A Size is more than specified size status
1318 One of the values mentioned below returned from
1319 call to UpdateSymFile
1320 EFI_SUCCESS - The function completed successfully.
1321 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
1322 EFI_ABORTED - An error occurred.UpdateSymFile
1323 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1328 UINT64 PalStartAddress
;
1330 UINTN RelativeAddress
;
1335 FIT_TABLE
*PalFitPtr
;
1337 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1340 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1344 FileSize
= _filelength (fileno (Fp
));
1345 if (FileSize
< 64) {
1346 Error (NULL
, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
1347 return EFI_INVALID_PARAMETER
;
1349 FileSize
-= SIZE_OF_PAL_HEADER
;
1352 if (VtfInfo
->PreferredSize
) {
1353 if (FileSize
> VtfInfo
->CompSize
) {
1354 Error (NULL
, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
1358 FileSize
= VtfInfo
->CompSize
;
1361 Buffer
= malloc ((UINTN
) FileSize
);
1362 if (Buffer
== NULL
) {
1363 return EFI_OUT_OF_RESOURCES
;
1365 memset (Buffer
, 0, (UINTN
) FileSize
);
1368 // Read, Get version Info and discard the PAL header.
1370 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1373 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1375 if (!VtfInfo
->VersionPresent
) {
1376 GetComponentVersionInfo (VtfInfo
, Buffer
);
1380 // Read PAL_A file in a buffer
1382 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1385 PalStartAddress
= Fv1EndAddress
- (SIZE_TO_OFFSET_PAL_A_END
+ FileSize
);
1386 Vtf1LastStartAddress
= PalStartAddress
;
1387 Vtf1TotalSize
+= (UINT32
) FileSize
;
1388 Status
= UpdateVtfBuffer (PalStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1390 AbsAddress
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1391 GetRelativeAddressInVtfBuffer (AbsAddress
, &RelativeAddress
, FIRST_VTF
);
1392 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1393 PalFitPtr
->CompAddress
= PalStartAddress
| IPF_CACHE_BIT
;
1394 //assert ((FileSize % 16) == 0);
1395 if ((FileSize
% 16) != 0) {
1396 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1397 return EFI_INVALID_PARAMETER
;
1400 PalFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1401 PalFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1402 PalFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1403 if (VtfInfo
->CheckSumRequired
) {
1404 PalFitPtr
->CheckSum
= 0;
1405 PalFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1413 // Update the SYM file for this component based on it's start address.
1415 Status
= UpdateSymFile (PalStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1416 if (EFI_ERROR (Status
)) {
1419 // At this time, SYM files are not required, so continue on error.
1427 CreateFitTableAndInitialize (
1428 IN PARSED_VTF_INFO
*VtfInfo
1432 Routine Description:
1434 This function creates and intializes FIT table which would be used to
1435 add component info inside this
1439 VtfInfo - Pointer to Parsed Info
1443 EFI_ABORTED - Aborted due to no size information
1444 EFI_SUCCESS - The function completed successfully
1448 UINT64 PalFitTableAdd
;
1450 UINT64 FitTableAddressOffset
;
1451 FIT_TABLE
*PalFitPtr
;
1452 FIT_TABLE
*FitStartPtr
;
1454 UINTN RelativeAddress
;
1457 if (!VtfInfo
->PreferredSize
) {
1458 Error (NULL
, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1462 if ((VtfInfo
->CompSize
% 16) != 0) {
1463 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
1466 PalFitTableAdd
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1467 GetRelativeAddressInVtfBuffer (PalFitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1468 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1469 PalFitTableAdd
= (PalFitPtr
->CompAddress
- VtfInfo
->CompSize
);
1471 FitTableAdd
= (PalFitPtr
->CompAddress
- 0x10) - VtfInfo
->CompSize
;
1472 FitTableAddressOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
1473 GetRelativeAddressInVtfBuffer (FitTableAddressOffset
, &RelativeAddress
, FIRST_VTF
);
1474 *(UINT64
*) RelativeAddress
= FitTableAdd
;
1476 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1479 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1481 FitStartPtr
= (FIT_TABLE
*) RelativeAddress
;
1483 strncpy ((CHAR8
*) &FitStartPtr
->CompAddress
, FIT_SIGNATURE
, 8); // "_FIT_ "
1484 assert (((VtfInfo
->CompSize
& 0x00FFFFFF) % 16) == 0);
1485 FitStartPtr
->CompSize
= (VtfInfo
->CompSize
& 0x00FFFFFF) / 16;
1486 FitStartPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1489 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1490 // determine what to do for things like the FV component that aren't easily checksummed.
1491 // The checksum will be done once we are done with all the componet update in the FIT
1494 FitStartPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1496 NumFitComp
= FitStartPtr
->CompSize
;
1501 // Intialize remaining FIT table space to UNUSED fit component type
1502 // so that when we need to create a FIT entry for a component, we can
1503 // locate a free one and use it.
1505 for (Index
= 0; Index
< (NumFitComp
- 1); Index
++) {
1506 FitStartPtr
->CvAndType
= 0x7F; // Initialize all with UNUSED
1510 Vtf1TotalSize
+= VtfInfo
->CompSize
;
1511 Vtf1LastStartAddress
-= VtfInfo
->CompSize
;
1524 Routine Description:
1526 Write Firmware Volume from memory to a file.
1530 FileName - Output File Name which needed to be created/
1532 LocType - The type of the VTF
1536 EFI_ABORTED - Returned due to one of the following resons:
1537 (a) Error Opening File
1538 (b) Failing to copy buffers
1539 EFI_SUCCESS - The fuction completes successfully
1546 UINTN RelativeAddress
;
1548 if (LocType
== FIRST_VTF
) {
1549 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1550 VtfBuffer
= (VOID
*) RelativeAddress
;
1552 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1553 VtfBuffer
= (VOID
*) RelativeAddress
;
1556 Fp
= fopen (FileName
, "wb");
1558 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1562 NumByte
= fwrite (VtfBuffer
, sizeof (UINT8
), (UINTN
) VtfSize
, Fp
);
1568 if (NumByte
!= (sizeof (UINT8
) * VtfSize
)) {
1569 Error (NULL
, 0, 0002, "Error writing file", FileName
);
1578 IN UINT64 StartAddress
,
1585 Routine Description:
1587 Update the Firmware Volume Buffer with requested buffer data
1591 StartAddress - StartAddress in buffer. This number will automatically
1592 point to right address in buffer where data needed
1594 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1595 DataSize - Size of the data needed to be copied.
1596 LocType - The type of the VTF: First or Second
1600 EFI_ABORTED - The input parameter is error
1601 EFI_SUCCESS - The function completed successfully
1605 UINT8
*LocalBufferPtrToWrite
;
1607 if (LocType
== FIRST_VTF
) {
1608 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf1LastStartAddress
| IPF_CACHE_BIT
)) {
1609 Error (NULL
, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
1613 LocalBufferPtrToWrite
= (UINT8
*) Vtf1EndBuffer
;
1615 LocalBufferPtrToWrite
-= (Fv1EndAddress
- StartAddress
);
1619 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf2LastStartAddress
| IPF_CACHE_BIT
)) {
1620 Error (NULL
, 0, 2000, "Invalid parameter", "Error StartAddress");
1623 LocalBufferPtrToWrite
= (UINT8
*) Vtf2EndBuffer
;
1624 LocalBufferPtrToWrite
-= (Fv2EndAddress
- StartAddress
);
1627 memcpy (LocalBufferPtrToWrite
, Buffer
, (UINTN
) DataSize
);
1634 IN UINT32 TotalVtfSize
,
1639 Routine Description:
1641 Update the Firmware Volume Buffer with requested buffer data
1645 TotalVtfSize - Size of the VTF
1646 Fileoffset - The start of the file relative to the start of the FV.
1647 LocType - The type of the VTF
1651 EFI_SUCCESS - The function completed successfully
1652 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1656 EFI_FFS_FILE_HEADER
*FileHeader
;
1657 UINTN RelativeAddress
;
1658 EFI_GUID EfiFirmwareVolumeTopFileGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1661 // Find the VTF file header location
1663 if (LocType
== FIRST_VTF
) {
1664 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1665 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1667 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1668 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1671 if (FileHeader
== NULL
) {
1672 return EFI_INVALID_PARAMETER
;
1678 memset (FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1679 memcpy (&FileHeader
->Name
, &EfiFirmwareVolumeTopFileGuid
, sizeof (EFI_GUID
));
1680 FileHeader
->Type
= EFI_FV_FILETYPE_RAW
;
1681 FileHeader
->Attributes
= FFS_ATTRIB_CHECKSUM
;
1684 // Now FileSize includes the EFI_FFS_FILE_HEADER
1686 FileHeader
->Size
[0] = (UINT8
) (TotalVtfSize
& 0x000000FF);
1687 FileHeader
->Size
[1] = (UINT8
) ((TotalVtfSize
& 0x0000FF00) >> 8);
1688 FileHeader
->Size
[2] = (UINT8
) ((TotalVtfSize
& 0x00FF0000) >> 16);
1691 // Fill in checksums and state, all three must be zero for the checksums.
1693 FileHeader
->IntegrityCheck
.Checksum
.Header
= 0;
1694 FileHeader
->IntegrityCheck
.Checksum
.File
= 0;
1695 FileHeader
->State
= 0;
1696 FileHeader
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1697 FileHeader
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) (FileHeader
+ 1), TotalVtfSize
- sizeof (EFI_FFS_FILE_HEADER
));
1698 FileHeader
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1704 ValidateAddressAndSize (
1705 IN UINT64 BaseAddress
,
1710 Routine Description:
1712 Update the Firmware Volume Buffer with requested buffer data
1716 BaseAddress - Base address for the Fw Volume.
1718 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1722 EFI_SUCCESS - The function completed successfully
1723 EFI_UNSUPPORTED - The input parameter is error
1727 if ((BaseAddress
>= 0) && (FwVolSize
> 0x40) && ((BaseAddress
+ FwVolSize
) % 8 == 0)) {
1731 return EFI_UNSUPPORTED
;
1735 UpdateIA32ResetVector (
1737 IN UINT64 FirstFwVSize
1741 Routine Description:
1743 Update the 16 byte IA32 Reset vector to maintain the compatibility
1747 FileName - Binary file name which contains the IA32 Reset vector info..
1748 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
1752 EFI_SUCCESS - The function completed successfully
1753 EFI_ABORTED - Invalid File Size
1754 EFI_INVALID_PARAMETER - Bad File Name
1755 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1760 UINT8
*LocalVtfBuffer
;
1765 if (!strcmp (FileName
, "")) {
1766 return EFI_INVALID_PARAMETER
;
1769 Fp
= fopen (FileName
, "rb");
1772 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1776 FileSize
= _filelength (fileno (Fp
));
1778 if (FileSize
> 16) {
1782 Buffer
= malloc (FileSize
);
1783 if (Buffer
== NULL
) {
1784 return EFI_OUT_OF_RESOURCES
;
1787 NumByteRead
= fread (Buffer
, sizeof (UINT8
), FileSize
, Fp
);
1789 LocalVtfBuffer
= (UINT8
*) Vtf1EndBuffer
- SIZE_IA32_RESET_VECT
;
1790 memcpy (LocalVtfBuffer
, Buffer
, FileSize
);
1808 Routine Description:
1810 This function cleans up any allocated buffer
1822 PARSED_VTF_INFO
*TempFileListPtr
;
1833 // Cleanup the buffer which was allocated to read the file names from FV.INF
1835 FileListPtr
= FileListHeadPtr
;
1836 while (FileListPtr
!= NULL
) {
1837 TempFileListPtr
= FileListPtr
->NextVtfInfo
;
1839 FileListPtr
= TempFileListPtr
;
1844 ProcessAndCreateVtf (
1849 Routine Description:
1851 This function process the link list created during INF file parsing
1852 and create component in VTF and updates its info in FIT table
1856 Size - Size of the Firmware Volume of which, this VTF belongs to.
1860 EFI_UNSUPPORTED - Unknown FIT type
1861 EFI_SUCCESS - The function completed successfully
1866 PARSED_VTF_INFO
*ParsedInfoPtr
;
1868 Status
= EFI_SUCCESS
;
1870 ParsedInfoPtr
= FileListHeadPtr
;
1872 while (ParsedInfoPtr
!= NULL
) {
1874 switch (ParsedInfoPtr
->CompType
) {
1876 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1878 case COMP_TYPE_FIT_HEADER
:
1879 //COMP_TYPE_FIT_HEADER 0x00
1880 Status
= CreateFitTableAndInitialize (ParsedInfoPtr
);
1884 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1886 case COMP_TYPE_FIT_PAL_A
:
1887 //COMP_TYPE_FIT_PAL_A 0x0F
1888 Status
= CreateAndUpdatePAL_A (ParsedInfoPtr
);
1891 // Based on VTF specification, once the PAL_A component has been written,
1892 // update the Firmware Volume info as FIT table. This will be utilized
1893 // to extract the Firmware Volume Start address where this VTF will be
1896 if (Status
== EFI_SUCCESS
) {
1897 UpdateFitEntryForFwVolume (Size
);
1901 case COMP_TYPE_FIT_FV_BOOT
:
1902 //COMP_TYPE_FIT_FV_BOOT 0x7E
1904 // Since FIT entry for Firmware Volume has been created and it is
1905 // located at (PAL_A start - 16 byte). So we will not process any
1906 // Firmware Volume related entry from INF file
1908 Status
= EFI_SUCCESS
;
1913 // Any other component type should be handled here. This will create the
1914 // image in specified VTF and create appropriate entry about this
1915 // component in FIT Entry.
1917 Status
= CreateAndUpdateComponent (ParsedInfoPtr
);
1918 if (EFI_ERROR (Status
)) {
1919 Error (NULL
, 0, 0002, "Error updating component", ParsedInfoPtr
->CompName
);
1925 ParsedInfoPtr
= ParsedInfoPtr
->NextVtfInfo
;
1932 IN UINT64 StartAddress1
,
1934 IN UINT64 StartAddress2
,
1940 Routine Description:
1942 This is the main function which will be called from application.
1946 StartAddress1 - The start address of the first VTF
1947 Size1 - The size of the first VTF
1948 StartAddress2 - The start address of the second VTF
1949 Size2 - The size of the second VTF
1950 fp - The pointer to BSF inf file
1954 EFI_OUT_OF_RESOURCES - Can not allocate memory
1955 The return value can be any of the values
1956 returned by the calls to following functions:
1957 GetVtfRelatedInfoFromInfFile
1959 UpdateIA32ResetVector
1968 Status
= EFI_UNSUPPORTED
;
1971 if (StartAddress2
== 0) {
1977 Fv1BaseAddress
= StartAddress1
;
1978 Fv1EndAddress
= Fv1BaseAddress
+ Size1
;
1979 if (Fv1EndAddress
!= 0x100000000ULL
|| Size1
< 0x100000) {
1980 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1981 if (Size1
< 0x100000) {
1982 Error (NULL
, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
1983 } else if (SecondVTF
!= TRUE
) {
1984 Error (NULL
, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
1987 return EFI_INVALID_PARAMETER
;
1991 // The image buffer for the First VTF
1993 Vtf1Buffer
= malloc ((UINTN
) Size1
);
1994 if (Vtf1Buffer
== NULL
) {
1995 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
1996 return EFI_OUT_OF_RESOURCES
;
1998 memset (Vtf1Buffer
, 0x00, (UINTN
) Size1
);
1999 Vtf1EndBuffer
= (UINT8
*) Vtf1Buffer
+ Size1
;
2000 Vtf1LastStartAddress
= Fv1EndAddress
| IPF_CACHE_BIT
;
2003 Fv2BaseAddress
= StartAddress2
;
2004 Fv2EndAddress
= Fv2BaseAddress
+ Size2
;
2005 if (Fv2EndAddress
!= StartAddress1
) {
2006 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
2007 if (SecondVTF
== TRUE
) {
2008 Error (NULL
, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
2009 Error (NULL
, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
2012 return EFI_INVALID_PARAMETER
;
2016 // The image buffer for the second VTF
2018 Vtf2Buffer
= malloc ((UINTN
) Size2
);
2019 if (Vtf2Buffer
== NULL
) {
2020 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2021 return EFI_OUT_OF_RESOURCES
;
2023 memset (Vtf2Buffer
, 0x00, (UINTN
) Size2
);
2024 Vtf2EndBuffer
= (UINT8
*) Vtf2Buffer
+ Size2
;
2025 Vtf2LastStartAddress
= Fv2EndAddress
| IPF_CACHE_BIT
;
2028 Status
= GetVtfRelatedInfoFromInfFile (VtfFP
);
2030 if (Status
!= EFI_SUCCESS
) {
2031 Error (NULL
, 0, 0003, "Error parsing file", "the input file.");
2036 Status
= ProcessAndCreateVtf (Size1
);
2037 if (Status
!= EFI_SUCCESS
) {
2042 if (SectionOptionFlag
) {
2043 Status
= UpdateIA32ResetVector (IA32BinFile
, Vtf1TotalSize
);
2044 if (Status
!= EFI_SUCCESS
) {
2051 // Re arrange the FIT Table for Ascending order of their FIT Type..
2056 // All components have been updated in FIT table. Now perform the FIT table
2057 // checksum. The following function will check if Checksum is required,
2058 // if yes, then it will perform the checksum otherwise not.
2060 CalculateFitTableChecksum ();
2063 // Write the FFS header
2065 Vtf1TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2066 Vtf1LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2068 Status
= UpdateFfsHeader (Vtf1TotalSize
, FIRST_VTF
);
2069 if (Status
!= EFI_SUCCESS
) {
2074 // Update the VTF buffer into specified VTF binary file
2076 Status
= WriteVtfBinary (OutFileName1
, Vtf1TotalSize
, FIRST_VTF
);
2079 Vtf2TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2080 Vtf2LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2081 Status
= UpdateFfsHeader (Vtf2TotalSize
, SECOND_VTF
);
2082 if (Status
!= EFI_SUCCESS
) {
2088 // Update the VTF buffer into specified VTF binary file
2090 Status
= WriteVtfBinary (OutFileName2
, Vtf2TotalSize
, SECOND_VTF
);
2099 PeimFixupInFitTable (
2100 IN UINT64 StartAddress
2104 Routine Description:
2106 This function is an entry point to fixup SAL-E entry point.
2110 StartAddress - StartAddress for PEIM.....
2114 EFI_SUCCESS - The function completed successfully
2115 EFI_ABORTED - Error Opening File
2116 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2122 UINT64
*StartAddressPtr
;
2126 StartAddressPtr
= malloc (sizeof (UINT64
));
2127 if (StartAddressPtr
== NULL
) {
2128 return EFI_OUT_OF_RESOURCES
;
2130 *StartAddressPtr
= StartAddress
;
2132 Fp
= fopen (OutFileName1
, "rb");
2135 Error (NULL
, 0, 0001, "Error opening file", OutFileName1
);
2136 if (StartAddressPtr
) {
2137 free (StartAddressPtr
);
2142 FirstFwVSize
= _filelength (fileno (Fp
));
2143 fseek (Fp
, (long) (FirstFwVSize
- (UINTN
) (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
)), SEEK_SET
);
2144 NumByte
= fwrite ((VOID
*) StartAddressPtr
, sizeof (UINT64
), 1, Fp
);
2150 if (StartAddressPtr
) {
2151 free (StartAddressPtr
);
2154 Status
= EFI_SUCCESS
;
2160 IN UINT64 BaseAddress
,
2161 IN CHAR8
*DestFileName
,
2162 IN CHAR8
*SourceFileName
,
2168 Routine Description:
2170 This function adds the SYM tokens in the source file to the destination file.
2171 The SYM tokens are updated to reflect the base address.
2175 BaseAddress - The base address for the new SYM tokens.
2176 DestFileName - The destination file.
2177 SourceFileName - The source file.
2178 FileSize - Size of bin file.
2182 EFI_SUCCESS - The function completed successfully.
2183 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2184 EFI_ABORTED - An error occurred.
2190 CHAR8 Buffer
[_MAX_PATH
];
2191 CHAR8 Type
[_MAX_PATH
];
2192 CHAR8 Address
[_MAX_PATH
];
2193 CHAR8 Section
[_MAX_PATH
];
2194 CHAR8 Token
[_MAX_PATH
];
2195 CHAR8 BaseToken
[_MAX_PATH
];
2196 UINT64 TokenAddress
;
2200 // Verify input parameters.
2202 if (BaseAddress
== 0 || DestFileName
== NULL
|| SourceFileName
== NULL
) {
2203 return EFI_INVALID_PARAMETER
;
2207 // Open the source file
2209 SourceFile
= fopen (SourceFileName
, "r");
2210 if (SourceFile
== NULL
) {
2213 // SYM files are not required.
2219 // Use the file name minus extension as the base for tokens
2221 strcpy (BaseToken
, SourceFileName
);
2222 strtok (BaseToken
, ". \t\n");
2223 strcat (BaseToken
, "__");
2226 // Open the destination file
2228 DestFile
= fopen (DestFileName
, "a+");
2229 if (DestFile
== NULL
) {
2230 fclose (SourceFile
);
2231 Error (NULL
, 0, 0001, "Error opening file", DestFileName
);
2236 // If this is the beginning of the output file, write the symbol format info.
2238 if (fseek (DestFile
, 0, SEEK_END
) != 0) {
2239 fclose (SourceFile
);
2241 Error (NULL
, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2245 StartLocation
= ftell (DestFile
);
2247 if (StartLocation
== 0) {
2248 fprintf (DestFile
, "TEXTSYM format | V1.0\n");
2249 } else if (StartLocation
== -1) {
2250 fclose (SourceFile
);
2252 Error (NULL
, 0, 2000, "Invalid parameter", "StartLocation error");
2257 // Read the first line
2259 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
2264 // Make sure it matches the expected sym format
2266 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
2267 fclose (SourceFile
);
2269 Error (NULL
, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2276 while (feof (SourceFile
) == 0) {
2281 if (fscanf (SourceFile
, "%s | %s | %s | %s\n", Type
, Address
, Section
, Token
) == 4) {
2284 // Get the token address
2286 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
2287 if (TokenAddress
> FileSize
) {
2289 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2295 // Add the base address, the size of the FFS file header and the size of the peim header.
2297 TokenAddress
+= BaseAddress
&~IPF_CACHE_BIT
;
2299 fprintf (DestFile
, "%s | %016llX | ", Type
, (unsigned long long) TokenAddress
);
2300 fprintf (DestFile
, "%s | %s\n %s\n", Section
, Token
, BaseToken
);
2304 fclose (SourceFile
);
2310 CalculateFitTableChecksum (
2315 Routine Description:
2317 This function will perform byte checksum on the FIT table, if the the checksum required
2318 field is set to CheckSum required. If the checksum is not required then checksum byte
2319 will have value as 0;.
2327 Status - Value returned by call to CalculateChecksum8 ()
2328 EFI_SUCCESS - The function completed successfully
2332 FIT_TABLE
*TmpFitPtr
;
2334 UINT64 FitTableAddOffset
;
2335 UINTN RelativeAddress
;
2339 // Read the Fit Table address from Itanium-based address map.
2341 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
2344 // Translate this Itanium-based address in terms of local buffer address which
2345 // contains the image for Boot Strapped File
2347 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
2348 FitTableAdd
= *(UINTN
*) RelativeAddress
;
2350 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
2352 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
2354 Size
= TmpFitPtr
->CompSize
* 16;
2356 if ((TmpFitPtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2357 TmpFitPtr
->CheckSum
= 0;
2358 TmpFitPtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) TmpFitPtr
, Size
);
2360 TmpFitPtr
->CheckSum
= 0;
2372 Routine Description:
2374 Displays the standard utility information to SDTOUT
2386 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
2395 Routine Description:
2397 Displays the utility usage syntax to STDOUT
2412 fprintf (stdout
, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME
);
2415 // Copyright declaration
2417 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
2421 fprintf (stdout
, "Options:\n");
2422 fprintf (stdout
, " -f Input_file, --filename Input_file\n\
2423 Input_file is name of the BS Image INF file\n");
2424 fprintf (stdout
, " -r BaseAddress, --baseaddr BaseAddress\n\
2425 BaseAddress is the starting address of Firmware Volume\n\
2426 where Boot Strapped Image will reside.\n");
2427 fprintf (stdout
, " -s FwVolumeSize, --size FwVolumeSize\n\
2428 FwVolumeSize is the size of Firmware Volume.\n");
2429 fprintf (stdout
, " -o FileName, --output FileName\n\
2430 File will be created to store the ouput content.\n");
2431 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
2432 fprintf (stdout
, " --version Show program's version number and exit.\n");
2433 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
2434 fprintf (stdout
, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
2435 fprintf (stdout
, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
2445 Routine Description:
2447 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2448 part of firmware volume image.
2452 argc - The count of the parameters
2453 argv - The parameters
2458 0 - No error conditions detected.
2459 1 - One or more of the input parameters is invalid.
2460 2 - A resource required by the utility was unavailable.
2461 - Most commonly this will be memory allocation or file creation.
2462 3 - GenFvImage.dll could not be loaded.
2463 4 - Error executing the GenFvImage dll.
2464 5 - Now this tool does not support the IA32 platform
2469 UINT64 StartAddress1
;
2470 UINT64 StartAddress2
;
2473 BOOLEAN FirstRoundO
;
2474 BOOLEAN FirstRoundB
;
2475 BOOLEAN FirstRoundS
;
2480 SetUtilityName (UTILITY_NAME
);
2483 // Initialize variables
2493 OutFileName1
= NULL
;
2494 OutFileName2
= NULL
;
2499 // Verify the correct number of arguments
2506 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
2511 if ((strcmp(argv
[1], "--version") == 0)) {
2517 // Parse the command line arguments
2519 for (Index
= 1; Index
< argc
; Index
+= 2) {
2520 if ((stricmp (argv
[Index
], "-o") == 0) || (stricmp (argv
[Index
], "--output") == 0)) {
2521 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2522 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
2526 // Get the output file name
2531 // It's the first output file name
2533 OutFileName1
= (CHAR8
*)argv
[Index
+1];
2534 FirstRoundO
= FALSE
;
2537 //It's the second output file name
2539 OutFileName2
= (CHAR8
*)argv
[Index
+1];
2544 if ((stricmp (argv
[Index
], "-f") == 0) || (stricmp (argv
[Index
], "--filename") == 0)) {
2545 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2546 Error (NULL
, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
2550 // Get the input VTF file name
2552 VtfFileName
= argv
[Index
+1];
2553 VtfFP
= fopen(VtfFileName
, "rb");
2554 if (VtfFP
== NULL
) {
2555 Error (NULL
, 0, 0001, "Error opening file", VtfFileName
);
2561 if ((stricmp (argv
[Index
], "-r") == 0) || (stricmp (argv
[Index
], "--baseaddr") == 0)) {
2563 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress1
);
2564 FirstRoundB
= FALSE
;
2566 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress2
);
2568 if (Status
!= EFI_SUCCESS
) {
2569 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv
[Index
+ 1]);
2575 if ((stricmp (argv
[Index
], "-s") == 0) || (stricmp (argv
[Index
], "--size") == 0)) {
2577 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize1
);
2578 FirstRoundS
= FALSE
;
2580 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize2
);
2584 if (Status
!= EFI_SUCCESS
) {
2585 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv
[Index
+ 1]);
2591 if ((stricmp (argv
[Index
], "-v") == 0) || (stricmp (argv
[Index
], "--verbose") == 0)) {
2597 if ((stricmp (argv
[Index
], "-q") == 0) || (stricmp (argv
[Index
], "--quiet") == 0)) {
2603 if ((stricmp (argv
[Index
], "-d") == 0) || (stricmp (argv
[Index
], "--debug") == 0)) {
2605 // debug level specified
2607 Status
= AsciiStringToUint64(argv
[Index
+ 1], FALSE
, &DebugLevel
);
2608 if (EFI_ERROR (Status
)) {
2609 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[Index
], argv
[Index
+ 1]);
2612 if (DebugLevel
> 9) {
2613 Error (NULL
, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv
[Index
+ 1]);
2616 if((DebugLevel
<= 9) &&(DebugLevel
>= 5)) {
2624 Error (NULL
, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv
[Index
]);
2628 if (VtfFP
== NULL
) {
2629 Error (NULL
, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2634 Error (NULL
, 0, 2000, "Invalid parameter", "No FV base address is specified");
2639 Error (NULL
, 0, 2000, "Invalid parameter", "No FV Size is specified");
2643 // All Parameters has been parsed, now set the message print level
2647 } else if (VerboseMode
) {
2649 } else if (DebugMode
) {
2650 SetPrintLevel(DebugLevel
);
2654 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
2657 if (VTF_OUTPUT
== FALSE
) {
2658 if (SecondVTF
== TRUE
) {
2659 OutFileName1
= VTF_OUTPUT_FILE1
;
2660 OutFileName2
= VTF_OUTPUT_FILE2
;
2662 OutFileName1
= VTF_OUTPUT_FILE1
;
2664 SymFileName
= VTF_SYM_FILE
;
2666 INTN OutFileNameLen
= strlen(OutFileName1
);
2669 for (Index
= OutFileNameLen
; Index
> 0; --Index
) {
2670 if (OutFileName1
[Index
] == '/' || OutFileName1
[Index
] == '\\') {
2675 SymFileName
= VTF_SYM_FILE
;
2677 INTN SymFileNameLen
= Index
+ 1 + strlen(VTF_SYM_FILE
);
2678 SymFileName
= malloc(SymFileNameLen
+ 1);
2679 memcpy(SymFileName
, OutFileName1
, Index
+ 1);
2680 memcpy(SymFileName
+ Index
+ 1, VTF_SYM_FILE
, strlen(VTF_SYM_FILE
));
2681 SymFileName
[SymFileNameLen
] = '\0';
2684 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, SymFileName
, NULL
);
2689 // Call the GenVtfImage
2692 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Start to generate the VTF image\n", NULL
);
2694 Status
= GenerateVtfImage (StartAddress1
, FwVolSize1
, StartAddress2
, FwVolSize2
, VtfFP
);
2696 if (EFI_ERROR (Status
)) {
2699 case EFI_INVALID_PARAMETER
:
2700 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2704 Error (NULL
, 0, 3000, "Invalid", "Error detected while creating the file image.");
2707 case EFI_OUT_OF_RESOURCES
:
2708 Error (NULL
, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2711 case EFI_VOLUME_CORRUPTED
:
2712 Error (NULL
, 0, 3000, "Invalid", "No base address was specified.");
2716 Error (NULL
, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status
);
2721 if (VtfFP
!= NULL
) {
2726 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "VTF image generated successful\n", NULL
);
2730 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2732 return GetUtilityStatus();