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.
129 memset (StrPtr
, 0, 40);
130 Token
= strtok (Str
, ".");
132 while (Token
!= NULL
) {
133 strcat (StrPtr
, Token
);
134 Token
= strtok (NULL
, ".");
144 *MajorVer
= (UINT8
) Major
;
145 *MinorVer
= (UINT8
) Minor
;
156 This function cleans up the line by removing all whitespace and
161 Line - The pointer of the string
169 CHAR8 TmpLine
[FILE_NAME_SIZE
];
176 // Change '#' to '//' for Comment style
178 if (((Ptr0
= strchr (Line
, '#')) != NULL
) || ((Ptr0
= strstr (Line
, "//")) != NULL
)) {
179 Line
[Ptr0
- Line
] = 0;
183 // Initialize counters
188 while ((Char
= Line
[Index
]) != 0) {
189 if ((Char
!= ' ') && (Char
!= '\t') && (Char
!= '\n') && (Char
!= '\r')) {
190 TmpLine
[Index2
++] = Char
;
196 strcpy (Line
, TmpLine
);
207 This function calculated number of valid lines in a input file.
211 Fp - Pointer to a file handle which has been opened.
219 CHAR8 Buff
[FILE_NAME_SIZE
];
220 while (fgets(Buff
, sizeof (Buff
), Fp
)) {
237 This function parses the input file and tokenize the string
241 Fp - Pointer to a file handle which has been opened.
250 CHAR8 Buff
[FILE_NAME_SIZE
+ 1];
251 CHAR8 Delimit
[] = "=";
253 Buff
[FILE_NAME_SIZE
] = '\0';
256 while (fgets (Buff
, FILE_NAME_SIZE
, Fp
) != NULL
) {
261 Token
= strtok (Buff
, Delimit
);
262 while (Token
!= NULL
) {
263 strcpy (*TokenStr
, Token
);
265 Token
= strtok (NULL
, Delimit
);
279 This function initializes the relevant global variable which is being
280 used to store the information retrieved from INF file. This also initializes
289 EFI_SUCCESS - The function completed successfully
290 EFI_OUT_OF_RESOURCES - Malloc failed.
295 FileListPtr
= malloc (sizeof (PARSED_VTF_INFO
));
297 if (FileListPtr
== NULL
) {
298 return EFI_OUT_OF_RESOURCES
;
301 FileListHeadPtr
= FileListPtr
;
302 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
303 FileListPtr
->NextVtfInfo
= NULL
;
305 remove (SymFileName
);
310 ParseAndUpdateComponents (
311 IN PARSED_VTF_INFO
*VtfInfo
317 This function initializes the relevant global variable which is being
318 used to store the information retrieved from INF file.
322 VtfInfo - A pointer to the VTF Info Structure
333 while (*TokenStr
!= NULL
&& (strnicmp (*TokenStr
, "COMP_NAME", 9) != 0)) {
335 if (strnicmp (*TokenStr
, "COMP_LOC", 8) == 0) {
337 if (strnicmp (*TokenStr
, "F", 1) == 0) {
338 VtfInfo
->LocationType
= FIRST_VTF
;
339 } else if (strnicmp (*TokenStr
, "S", 1) == 0) {
340 VtfInfo
->LocationType
= SECOND_VTF
;
342 VtfInfo
->LocationType
= NONE
;
344 } else if (strnicmp (*TokenStr
, "COMP_TYPE", 9) == 0) {
346 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
347 Error (NULL
, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr
);
351 VtfInfo
->CompType
= (UINT8
) StringValue
;
352 } else if (strnicmp (*TokenStr
, "COMP_VER", 8) == 0) {
354 if (strnicmp (*TokenStr
, "-", 1) == 0) {
355 VtfInfo
->VersionPresent
= FALSE
;
356 VtfInfo
->MajorVer
= 0;
357 VtfInfo
->MinorVer
= 0;
359 VtfInfo
->VersionPresent
= TRUE
;
360 ConvertVersionInfo (*TokenStr
, &VtfInfo
->MajorVer
, &VtfInfo
->MinorVer
);
362 } else if (strnicmp (*TokenStr
, "COMP_BIN", 8) == 0) {
364 strcpy (VtfInfo
->CompBinName
, *TokenStr
);
365 } else if (strnicmp (*TokenStr
, "COMP_SYM", 8) == 0) {
367 strcpy (VtfInfo
->CompSymName
, *TokenStr
);
368 } else if (strnicmp (*TokenStr
, "COMP_SIZE", 9) == 0) {
370 if (strnicmp (*TokenStr
, "-", 1) == 0) {
371 VtfInfo
->PreferredSize
= FALSE
;
372 VtfInfo
->CompSize
= 0;
374 VtfInfo
->PreferredSize
= TRUE
;
375 if (AsciiStringToUint64 (*TokenStr
, FALSE
, &StringValue
) != EFI_SUCCESS
) {
376 Error (NULL
, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr
);
380 VtfInfo
->CompSize
= (UINTN
) StringValue
;
383 } else if (strnicmp (*TokenStr
, "COMP_CS", 7) == 0) {
385 if (strnicmp (*TokenStr
, "1", 1) == 0) {
386 VtfInfo
->CheckSumRequired
= 1;
387 } else if (strnicmp (*TokenStr
, "0", 1) == 0) {
388 VtfInfo
->CheckSumRequired
= 0;
390 Error (NULL
, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
395 if (*TokenStr
== NULL
) {
402 InitializeInFileInfo (
409 This function intializes the relevant global variable which is being
410 used to store the information retrieved from INF file.
423 SectionOptionFlag
= 0;
425 TokenStr
= OrgStrTokPtr
;
427 while (*TokenStr
!= NULL
) {
428 if (strnicmp (*TokenStr
, "[OPTIONS]", 9) == 0) {
429 SectionOptionFlag
= 1;
433 if (strnicmp (*TokenStr
, "[COMPONENTS]", 12) == 0) {
434 if (FileListPtr
== NULL
) {
435 FileListPtr
= FileListHeadPtr
;
439 SectionOptionFlag
= 0;
443 if (SectionOptionFlag
) {
444 if (stricmp (*TokenStr
, "IA32_RST_BIN") == 0) {
446 strcpy (IA32BinFile
, *TokenStr
);
450 if (SectionCompFlag
) {
451 if (stricmp (*TokenStr
, "COMP_NAME") == 0) {
453 strcpy (FileListPtr
->CompName
, *TokenStr
);
455 ParseAndUpdateComponents (FileListPtr
);
458 if (*TokenStr
!= NULL
) {
459 FileListPtr
->NextVtfInfo
= malloc (sizeof (PARSED_VTF_INFO
));
460 if (FileListPtr
->NextVtfInfo
== NULL
) {
461 Error (NULL
, 0, 4003, "Resource", "Out of memory resources.", NULL
);
464 FileListPtr
= FileListPtr
->NextVtfInfo
;
465 memset (FileListPtr
, 0, sizeof (PARSED_VTF_INFO
));
466 FileListPtr
->NextVtfInfo
= NULL
;
478 GetVtfRelatedInfoFromInfFile (
485 This function reads the input file, parse it and create a list of tokens
486 which is parsed and used, to intialize the data related to VTF
490 FileName - FileName which needed to be read to parse data
494 EFI_ABORTED - Error in opening file
495 EFI_INVALID_PARAMETER - File doesn't contain any valid information
496 EFI_OUT_OF_RESOURCES - Malloc Failed
497 EFI_SUCCESS - The function completed successfully
506 Status
= EFI_SUCCESS
;
509 Error (NULL
, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
515 if (ValidLineNum
== 0) {
516 Error (NULL
, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
517 return EFI_INVALID_PARAMETER
;
520 TokenStr
= (CHAR8
**) malloc (sizeof (UINTN
) * (2 * ValidLineNum
+ 1));
522 if (TokenStr
== NULL
) {
523 return EFI_OUT_OF_RESOURCES
;
526 memset (TokenStr
, 0, (sizeof (UINTN
) * (2 * ValidLineNum
+ 1)));
527 OrgStrTokPtr
= TokenStr
;
529 for (Index
= 0; Index
< (2 * ValidLineNum
); Index
++) {
530 *TokenStr
= (CHAR8
*)malloc (sizeof (CHAR8
) * FILE_NAME_SIZE
);
532 if (*TokenStr
== NULL
) {
533 Status
= EFI_OUT_OF_RESOURCES
;
537 memset (*TokenStr
, 0, FILE_NAME_SIZE
);
541 TokenStr
= OrgStrTokPtr
;
542 fseek (Fp
, 0L, SEEK_SET
);
544 Status
= InitializeComps ();
546 if (Status
!= EFI_SUCCESS
) {
550 Status
= ParseInputFile (Fp
);
551 if (Status
!= EFI_SUCCESS
) {
555 InitializeInFileInfo ();
559 for (Index1
= 0; Index1
< Index
; Index1
++) {
560 free (OrgStrTokPtr
[Index1
]);
569 GetRelativeAddressInVtfBuffer (
571 IN OUT UINTN
*RelativeAddress
,
578 This function checks for the address alignmnet for specified data boundary. In
579 case the address is not aligned, it returns FALSE and the amount of data in
580 terms of byte needed to adjust to get the boundary alignmnet. If data is
581 aligned, TRUE will be returned.
585 Address - The address of the flash map space
586 RelativeAddress - The relative address of the Buffer
587 LocType - The type of the VTF
598 if (LocType
== FIRST_VTF
) {
599 LocalBuff
= (UINT8
*) Vtf1EndBuffer
;
600 TempAddress
= Fv1EndAddress
- Address
;
601 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
603 LocalBuff
= (UINT8
*) Vtf2EndBuffer
;
604 TempAddress
= Fv2EndAddress
- Address
;
605 *RelativeAddress
= (UINTN
) LocalBuff
- (UINTN
) TempAddress
;
610 GetComponentVersionInfo (
611 IN OUT PARSED_VTF_INFO
*VtfInfo
,
617 This function will extract the version information from File
621 VtfInfo - A Pointer to the VTF Info Structure
622 Buffer - A Pointer to type UINT8
626 EFI_SUCCESS - The function completed successfully
627 EFI_INVALID_PARAMETER - The parameter is invalid
634 switch (VtfInfo
->CompType
) {
636 case COMP_TYPE_FIT_PAL_A
:
637 case COMP_TYPE_FIT_PAL_B
:
638 memcpy (&VersionInfo
, (Buffer
+ 8), sizeof (UINT16
));
639 VtfInfo
->MajorVer
= (UINT8
) ((VersionInfo
& 0xFF00) >> 8);
640 VtfInfo
->MinorVer
= (UINT8
) (VersionInfo
& 0x00FF);
641 Status
= EFI_SUCCESS
;
645 Status
= EFI_INVALID_PARAMETER
;
653 CheckAddressAlignment (
655 IN UINT64 AlignmentData
,
656 IN OUT UINT64
*AlignAdjustByte
662 This function checks for the address alignmnet for specified data boundary. In
663 case the address is not aligned, it returns FALSE and the amount of data in
664 terms of byte needed to adjust to get the boundary alignmnet. If data is
665 aligned, TRUE will be returned.
669 Address - Pointer to buffer containing byte data of component.
670 AlignmentData - DataSize for which address needed to be aligned
671 AlignAdjustByte - Number of bytes needed to adjust alignment.
675 TRUE - Address is aligned to specific data size boundary
676 FALSE - Address in not aligned to specified data size boundary
677 - Add/Subtract AlignAdjustByte to aling the address.
682 // Check if the assigned address is on address boundary. If not, it will
683 // return the remaining byte required to adjust the address for specified
686 *AlignAdjustByte
= (Address
% AlignmentData
);
688 if (*AlignAdjustByte
== 0) {
696 GetFitTableStartAddress (
697 IN OUT FIT_TABLE
**FitTable
703 Get the FIT table start address in VTF Buffer
707 FitTable - Pointer to available fit table where new component can be added
711 EFI_SUCCESS - The function completed successfully
716 UINT64 FitTableAddOffset
;
717 UINTN RelativeAddress
;
720 // Read the Fit Table address from Itanium-based address map.
722 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
725 // Translate this Itanium-based address in terms of local buffer address which
726 // contains the image for Boot Strapped File. The relative address will be
727 // the address of fit table VTF buffer.
729 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
730 FitTableAdd
= *(UINTN
*) RelativeAddress
;
733 // The FitTableAdd is the extracted Itanium based address pointing to FIT
734 // table. The relative address will return its actual location in VTF
737 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
739 *FitTable
= (FIT_TABLE
*) RelativeAddress
;
745 GetNextAvailableFitPtr (
746 IN FIT_TABLE
**FitPtr
752 Get the FIT table address and locate the free space in fit where we can add
753 new component. In this process, this function locates the fit table using
754 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
755 and locate the available location in FIT table to be used by new components.
756 If there are any Fit table which areg not being used contains ComponentType
757 field as 0x7F. If needed we can change this and spec this out.
761 FitPtr - Pointer to available fit table where new component can be added
765 EFI_SUCCESS - The function completed successfully
769 FIT_TABLE
*TmpFitPtr
;
771 UINT64 FitTableAddOffset
;
773 UINTN NumFitComponents
;
774 UINTN RelativeAddress
;
777 // Read the Fit Table address from Itanium-based address map.
779 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
782 // Translate this Itanium-based address in terms of local buffer address which
783 // contains the image for Boot Strapped File. The relative address will be
784 // the address of fit table VTF buffer.
786 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
787 FitTableAdd
= *(UINTN
*) RelativeAddress
;
790 // The FitTableAdd is the extracted Itanium based address pointing to FIT
791 // table. The relative address will return its actual location in VTF
794 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
796 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
797 NumFitComponents
= TmpFitPtr
->CompSize
;
799 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
800 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_UNUSED
) {
820 This function is used by qsort to sort the FIT table based upon Component
821 Type in their incresing order.
825 Arg1 - Pointer to Arg1
826 Arg2 - Pointer to Arg2
834 if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) > (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
836 } else if ((((FIT_TABLE
*) Arg1
)->CvAndType
& FIT_TYPE_MASK
) < (((FIT_TABLE
*) Arg2
)->CvAndType
& FIT_TYPE_MASK
)) {
851 This function is used by qsort to sort the FIT table based upon Component
852 Type in their incresing order.
865 FIT_TABLE
*TmpFitPtr
;
866 UINTN NumFitComponents
;
869 GetFitTableStartAddress (&FitTable
);
870 TmpFitPtr
= FitTable
;
871 NumFitComponents
= 0;
872 for (Index
= 0; Index
< FitTable
->CompSize
; Index
++) {
873 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) != COMP_TYPE_FIT_UNUSED
) {
874 NumFitComponents
+= 1;
878 qsort ((VOID
*) FitTable
, NumFitComponents
, sizeof (FIT_TABLE
), CompareItems
);
882 UpdateFitEntryForFwVolume (
889 This function updates the information about Firmware Volume in FIT TABLE.
890 This FIT table has to be immediately below the PAL_A Start and it contains
891 component type and address information. Other information can't be
892 created this time so we would need to fix it up..
897 Size - Firmware Volume Size
905 FIT_TABLE
*CompFitPtr
;
906 UINTN RelativeAddress
;
909 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
911 Vtf1LastStartAddress
-= 0x10;
912 Vtf1TotalSize
+= 0x10;
914 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
916 CompFitPtr
= (FIT_TABLE
*) RelativeAddress
;
917 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
920 // Since we don't have any information about its location in Firmware Volume,
921 // initialize address to 0. This will be updated once Firmware Volume is
922 // being build and its current address will be fixed in FIT table. Currently
923 // we haven't implemented it so far and working on architectural clarafication
926 // Firmware Volume Size in 16 byte block
928 CompFitPtr
->CompSize
= ((UINT32
) Size
) / 16;
931 // Since Firmware Volume does not exist by the time we create this FIT info
932 // this should be fixedup from Firmware Volume creation tool. We haven't
933 // worked out a method so far.
935 CompFitPtr
->CompVersion
= MAKE_VERSION (0, 0);
938 // Since we don't have any info about this file, we are making sure that
939 // checksum is not needed.
941 CompFitPtr
->CvAndType
= CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT
);
944 // Since non VTF component will reside outside the VTF, we will not have its
945 // binary image while creating VTF, hence we will not perform checksum at
946 // this time. Once Firmware Volume is being created which will contain this
947 // VTF, it will fix the FIT table for all the non VTF component and hence
950 CompFitPtr
->CheckSum
= 0;
954 UpdateFitEntryForNonVTFComp (
955 IN PARSED_VTF_INFO
*VtfInfo
961 This function updates the information about non VTF component in FIT TABLE.
962 Since non VTF componets binaries are not part of VTF binary, we would still
963 be required to update its location information in Firmware Volume, inside
968 VtfInfo - Pointer to VTF Info Structure
972 EFI_ABORTED - The function fails to update the component in FIT
973 EFI_SUCCESS - The function completed successfully
977 FIT_TABLE
*CompFitPtr
;
980 // Scan the FIT table for available space
982 GetNextAvailableFitPtr (&CompFitPtr
);
983 if (CompFitPtr
== NULL
) {
984 Error (NULL
, 0, 5003, "Invalid", "Can't update this component in FIT");
989 // Since we don't have any information about its location in Firmware Volume,
990 // initialize address to 0. This will be updated once Firmware Volume is
991 // being build and its current address will be fixed in FIT table
993 CompFitPtr
->CompAddress
= 0;
994 CompFitPtr
->CompSize
= VtfInfo
->CompSize
;
995 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
996 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
999 // Since non VTF component will reside outside the VTF, we will not have its
1000 // binary image while creating VTF, hence we will not perform checksum at
1001 // this time. Once Firmware Volume is being created which will contain this
1002 // VTF, it will fix the FIT table for all the non VTF component and hence
1005 CompFitPtr
->CheckSum
= 0;
1008 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
1009 // address of Firmware Volume in which this VTF will be attached.
1011 if ((CompFitPtr
->CvAndType
& 0x7F) == COMP_TYPE_FIT_FV_BOOT
) {
1012 CompFitPtr
->CompAddress
= Fv1BaseAddress
;
1020 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
1021 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
1022 // CORE moves in Firmware Volume, we would need to modify this function to be
1023 // used with a API which will detect PEICORE component while building Firmware
1024 // Volume and update its entry in FIT table as well as in Itanium address space
1025 // as per Intel?Itanium(TM) SAL address space
1029 IN PARSED_VTF_INFO
*VtfInfo
,
1030 IN UINT64
*CompStartAddress
1034 Routine Description:
1036 This function updated the architectural entry point in IPF, SALE_ENTRY.
1040 VtfInfo - Pointer to VTF Info Structure
1041 CompStartAddress - Pointer to Component Start Address
1045 EFI_INVALID_PARAMETER - The parameter is invalid
1046 EFI_SUCCESS - The function completed successfully
1050 UINTN RelativeAddress
;
1055 CHAR8 Buff
[FILE_NAME_SIZE
];
1058 CHAR8 OffsetStr
[30];
1064 Fp
= fopen (VtfInfo
->CompSymName
, "rb");
1067 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompSymName
);
1068 return EFI_INVALID_PARAMETER
;
1071 while (fgets (Buff
, sizeof (Buff
), Fp
) != NULL
) {
1074 "%s %s %s %s %s %s %s",
1083 if (strnicmp (Token
, "SALE_ENTRY", 10) == 0) {
1088 Offset
= strtoul (OffsetStr
, NULL
, 16);
1090 *CompStartAddress
+= Offset
;
1091 SalEntryAdd
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
);
1093 GetRelativeAddressInVtfBuffer (SalEntryAdd
, &RelativeAddress
, FIRST_VTF
);
1095 memcpy ((VOID
*) RelativeAddress
, (VOID
*) CompStartAddress
, sizeof (UINT64
));
1105 CreateAndUpdateComponent (
1106 IN PARSED_VTF_INFO
*VtfInfo
1110 Routine Description:
1112 This function reads the binary file for each components and update them
1113 in VTF Buffer as well as in FIT table. If the component is located in non
1114 VTF area, only the FIT table address will be updated
1118 VtfInfo - Pointer to Parsed Info
1122 EFI_SUCCESS - The function completed successful
1123 EFI_ABORTED - Aborted due to one of the many reasons like:
1124 (a) Component Size greater than the specified size.
1125 (b) Error opening files.
1127 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1128 EFI_OUT_OF_RESOURCES Memory allocation failure.
1133 UINT64 CompStartAddress
;
1136 UINT64 NumAdjustByte
;
1139 FIT_TABLE
*CompFitPtr
;
1142 if (VtfInfo
->LocationType
== NONE
) {
1143 UpdateFitEntryForNonVTFComp (VtfInfo
);
1147 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1150 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1154 FileSize
= _filelength (fileno (Fp
));
1155 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1158 // BUGBUG: Satish to correct
1160 FileSize
-= SIZE_OF_PAL_HEADER
;
1163 if (VtfInfo
->PreferredSize
) {
1164 if (FileSize
> VtfInfo
->CompSize
) {
1165 Error (NULL
, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1169 FileSize
= VtfInfo
->CompSize
;
1172 Buffer
= malloc ((UINTN
) FileSize
);
1173 if (Buffer
== NULL
) {
1174 return EFI_OUT_OF_RESOURCES
;
1176 memset (Buffer
, 0, (UINTN
) FileSize
);
1178 if ((VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) || (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_A_SPECIFIC
)) {
1181 // Read first 64 bytes of PAL header and use it to find version info
1183 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1186 // PAL header contains the version info. Currently, we will use the header
1187 // to read version info and then discard.
1189 if (!VtfInfo
->VersionPresent
) {
1190 GetComponentVersionInfo (VtfInfo
, Buffer
);
1194 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1198 // If it is non PAL_B component, pass the entire buffer to get the version
1199 // info and implement any specific case inside GetComponentVersionInfo.
1201 if (VtfInfo
->CompType
!= COMP_TYPE_FIT_PAL_B
) {
1202 if (!VtfInfo
->VersionPresent
) {
1203 GetComponentVersionInfo (VtfInfo
, Buffer
);
1207 if (VtfInfo
->LocationType
== SECOND_VTF
) {
1209 CompStartAddress
= (Vtf2LastStartAddress
- FileSize
);
1211 CompStartAddress
= (Vtf1LastStartAddress
- FileSize
);
1214 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PAL_B
) {
1215 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 32 * 1024, &NumAdjustByte
);
1217 Aligncheck
= CheckAddressAlignment (CompStartAddress
, 8, &NumAdjustByte
);
1221 CompStartAddress
-= NumAdjustByte
;
1224 if (VtfInfo
->LocationType
== SECOND_VTF
&& SecondVTF
== TRUE
) {
1225 Vtf2LastStartAddress
= CompStartAddress
;
1226 Vtf2TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1227 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, SECOND_VTF
);
1228 } else if (VtfInfo
->LocationType
== FIRST_VTF
) {
1229 Vtf1LastStartAddress
= CompStartAddress
;
1230 Vtf1TotalSize
+= (UINT32
) (FileSize
+ NumAdjustByte
);
1231 Status
= UpdateVtfBuffer (CompStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1233 Error (NULL
, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
1234 return EFI_INVALID_PARAMETER
;
1237 if (EFI_ERROR (Status
)) {
1241 GetNextAvailableFitPtr (&CompFitPtr
);
1243 CompFitPtr
->CompAddress
= CompStartAddress
| IPF_CACHE_BIT
;
1244 if ((FileSize
% 16) != 0) {
1245 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1246 return EFI_INVALID_PARAMETER
;
1248 //assert ((FileSize % 16) == 0);
1249 CompFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1250 CompFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1251 CompFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1252 if (VtfInfo
->CheckSumRequired
) {
1253 CompFitPtr
->CheckSum
= 0;
1254 CompFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1265 // Update the SYM file for this component based on it's start address.
1267 Status
= UpdateSymFile (CompStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1268 if (EFI_ERROR (Status
)) {
1271 // At this time, SYM files are not required, so continue on error.
1275 // !!!!!!!!!!!!!!!!!!!!!
1277 // This part of the code is a temporary line since PEICORE is going to be inside
1278 // VTF till we work out how to determine the SALE_ENTRY through it. We will need
1279 // to clarify so many related questions
1280 // !!!!!!!!!!!!!!!!!!!!!!!
1282 if (VtfInfo
->CompType
== COMP_TYPE_FIT_PEICORE
) {
1283 Status
= UpdateEntryPoint (VtfInfo
, &CompStartAddress
);
1290 CreateAndUpdatePAL_A (
1291 IN PARSED_VTF_INFO
*VtfInfo
1295 Routine Description:
1297 This function reads the binary file for each components and update them
1298 in VTF Buffer as well as FIT table
1302 VtfInfo - Pointer to Parsed Info
1306 EFI_ABORTED - Due to one of the following reasons:
1307 (a)Error Opening File
1308 (b)The PAL_A Size is more than specified size status
1309 One of the values mentioned below returned from
1310 call to UpdateSymFile
1311 EFI_SUCCESS - The function completed successfully.
1312 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
1313 EFI_ABORTED - An error occurred.UpdateSymFile
1314 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1319 UINT64 PalStartAddress
;
1321 UINTN RelativeAddress
;
1326 FIT_TABLE
*PalFitPtr
;
1328 Fp
= fopen (VtfInfo
->CompBinName
, "rb");
1331 Error (NULL
, 0, 0001, "Error opening file", VtfInfo
->CompBinName
);
1335 FileSize
= _filelength (fileno (Fp
));
1336 if (FileSize
< 64) {
1337 Error (NULL
, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
1338 return EFI_INVALID_PARAMETER
;
1340 FileSize
-= SIZE_OF_PAL_HEADER
;
1343 if (VtfInfo
->PreferredSize
) {
1344 if (FileSize
> VtfInfo
->CompSize
) {
1345 Error (NULL
, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
1349 FileSize
= VtfInfo
->CompSize
;
1352 Buffer
= malloc ((UINTN
) FileSize
);
1353 if (Buffer
== NULL
) {
1354 return EFI_OUT_OF_RESOURCES
;
1356 memset (Buffer
, 0, (UINTN
) FileSize
);
1359 // Read, Get version Info and discard the PAL header.
1361 NumByteRead
= fread (Buffer
, sizeof (UINT8
), SIZE_OF_PAL_HEADER
, Fp
);
1364 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1366 if (!VtfInfo
->VersionPresent
) {
1367 GetComponentVersionInfo (VtfInfo
, Buffer
);
1371 // Read PAL_A file in a buffer
1373 NumByteRead
= fread (Buffer
, sizeof (UINT8
), (UINTN
) FileSize
, Fp
);
1376 PalStartAddress
= Fv1EndAddress
- (SIZE_TO_OFFSET_PAL_A_END
+ FileSize
);
1377 Vtf1LastStartAddress
= PalStartAddress
;
1378 Vtf1TotalSize
+= (UINT32
) FileSize
;
1379 Status
= UpdateVtfBuffer (PalStartAddress
, Buffer
, FileSize
, FIRST_VTF
);
1381 AbsAddress
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1382 GetRelativeAddressInVtfBuffer (AbsAddress
, &RelativeAddress
, FIRST_VTF
);
1383 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1384 PalFitPtr
->CompAddress
= PalStartAddress
| IPF_CACHE_BIT
;
1385 //assert ((FileSize % 16) == 0);
1386 if ((FileSize
% 16) != 0) {
1387 Error (NULL
, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1388 return EFI_INVALID_PARAMETER
;
1391 PalFitPtr
->CompSize
= (UINT32
) (FileSize
/ 16);
1392 PalFitPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1393 PalFitPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1394 if (VtfInfo
->CheckSumRequired
) {
1395 PalFitPtr
->CheckSum
= 0;
1396 PalFitPtr
->CheckSum
= CalculateChecksum8 (Buffer
, (UINTN
) FileSize
);
1404 // Update the SYM file for this component based on it's start address.
1406 Status
= UpdateSymFile (PalStartAddress
, SymFileName
, VtfInfo
->CompSymName
, FileSize
);
1407 if (EFI_ERROR (Status
)) {
1410 // At this time, SYM files are not required, so continue on error.
1418 CreateFitTableAndInitialize (
1419 IN PARSED_VTF_INFO
*VtfInfo
1423 Routine Description:
1425 This function creates and intializes FIT table which would be used to
1426 add component info inside this
1430 VtfInfo - Pointer to Parsed Info
1434 EFI_ABORTED - Aborted due to no size information
1435 EFI_SUCCESS - The function completed successfully
1439 UINT64 PalFitTableAdd
;
1441 UINT64 FitTableAddressOffset
;
1442 FIT_TABLE
*PalFitPtr
;
1443 FIT_TABLE
*FitStartPtr
;
1445 UINTN RelativeAddress
;
1448 if (!VtfInfo
->PreferredSize
) {
1449 Error (NULL
, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1453 if ((VtfInfo
->CompSize
% 16) != 0) {
1454 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
1457 PalFitTableAdd
= Fv1EndAddress
- SIZE_TO_PAL_A_FIT
;
1458 GetRelativeAddressInVtfBuffer (PalFitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1459 PalFitPtr
= (FIT_TABLE
*) RelativeAddress
;
1460 PalFitTableAdd
= (PalFitPtr
->CompAddress
- VtfInfo
->CompSize
);
1462 FitTableAdd
= (PalFitPtr
->CompAddress
- 0x10) - VtfInfo
->CompSize
;
1463 FitTableAddressOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
1464 GetRelativeAddressInVtfBuffer (FitTableAddressOffset
, &RelativeAddress
, FIRST_VTF
);
1465 *(UINT64
*) RelativeAddress
= FitTableAdd
;
1467 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
1470 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1472 FitStartPtr
= (FIT_TABLE
*) RelativeAddress
;
1474 strncpy ((CHAR8
*) &FitStartPtr
->CompAddress
, FIT_SIGNATURE
, 8); // "_FIT_ "
1475 assert (((VtfInfo
->CompSize
& 0x00FFFFFF) % 16) == 0);
1476 FitStartPtr
->CompSize
= (VtfInfo
->CompSize
& 0x00FFFFFF) / 16;
1477 FitStartPtr
->CompVersion
= MAKE_VERSION (VtfInfo
->MajorVer
, VtfInfo
->MinorVer
);
1480 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1481 // determine what to do for things like the FV component that aren't easily checksummed.
1482 // The checksum will be done once we are done with all the componet update in the FIT
1485 FitStartPtr
->CvAndType
= CV_N_TYPE (VtfInfo
->CheckSumRequired
, VtfInfo
->CompType
);
1487 NumFitComp
= FitStartPtr
->CompSize
;
1492 // Intialize remaining FIT table space to UNUSED fit component type
1493 // so that when we need to create a FIT entry for a component, we can
1494 // locate a free one and use it.
1496 for (Index
= 0; Index
< (NumFitComp
- 1); Index
++) {
1497 FitStartPtr
->CvAndType
= 0x7F; // Initialize all with UNUSED
1501 Vtf1TotalSize
+= VtfInfo
->CompSize
;
1502 Vtf1LastStartAddress
-= VtfInfo
->CompSize
;
1515 Routine Description:
1517 Write Firmware Volume from memory to a file.
1521 FileName - Output File Name which needed to be created/
1523 LocType - The type of the VTF
1527 EFI_ABORTED - Returned due to one of the following resons:
1528 (a) Error Opening File
1529 (b) Failing to copy buffers
1530 EFI_SUCCESS - The fuction completes successfully
1537 UINTN RelativeAddress
;
1539 if (LocType
== FIRST_VTF
) {
1540 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1541 VtfBuffer
= (VOID
*) RelativeAddress
;
1543 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1544 VtfBuffer
= (VOID
*) RelativeAddress
;
1547 Fp
= fopen (FileName
, "wb");
1549 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1553 NumByte
= fwrite (VtfBuffer
, sizeof (UINT8
), (UINTN
) VtfSize
, Fp
);
1559 if (NumByte
!= (sizeof (UINT8
) * VtfSize
)) {
1560 Error (NULL
, 0, 0002, "Error writing file", FileName
);
1569 IN UINT64 StartAddress
,
1576 Routine Description:
1578 Update the Firmware Volume Buffer with requested buffer data
1582 StartAddress - StartAddress in buffer. This number will automatically
1583 point to right address in buffer where data needed
1585 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1586 DataSize - Size of the data needed to be copied.
1587 LocType - The type of the VTF: First or Second
1591 EFI_ABORTED - The input parameter is error
1592 EFI_SUCCESS - The function completed successfully
1596 UINT8
*LocalBufferPtrToWrite
;
1598 if (LocType
== FIRST_VTF
) {
1599 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf1LastStartAddress
| IPF_CACHE_BIT
)) {
1600 Error (NULL
, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
1604 LocalBufferPtrToWrite
= (UINT8
*) Vtf1EndBuffer
;
1606 LocalBufferPtrToWrite
-= (Fv1EndAddress
- StartAddress
);
1610 if ((StartAddress
| IPF_CACHE_BIT
) < (Vtf2LastStartAddress
| IPF_CACHE_BIT
)) {
1611 Error (NULL
, 0, 2000, "Invalid parameter", "Error StartAddress");
1614 LocalBufferPtrToWrite
= (UINT8
*) Vtf2EndBuffer
;
1615 LocalBufferPtrToWrite
-= (Fv2EndAddress
- StartAddress
);
1618 memcpy (LocalBufferPtrToWrite
, Buffer
, (UINTN
) DataSize
);
1625 IN UINT32 TotalVtfSize
,
1630 Routine Description:
1632 Update the Firmware Volume Buffer with requested buffer data
1636 TotalVtfSize - Size of the VTF
1637 Fileoffset - The start of the file relative to the start of the FV.
1638 LocType - The type of the VTF
1642 EFI_SUCCESS - The function completed successfully
1643 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1647 EFI_FFS_FILE_HEADER
*FileHeader
;
1648 UINTN RelativeAddress
;
1649 EFI_GUID EfiFirmwareVolumeTopFileGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1652 // Find the VTF file header location
1654 if (LocType
== FIRST_VTF
) {
1655 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress
, &RelativeAddress
, FIRST_VTF
);
1656 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1658 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress
, &RelativeAddress
, SECOND_VTF
);
1659 FileHeader
= (EFI_FFS_FILE_HEADER
*) RelativeAddress
;
1662 if (FileHeader
== NULL
) {
1663 return EFI_INVALID_PARAMETER
;
1669 memset (FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1670 memcpy (&FileHeader
->Name
, &EfiFirmwareVolumeTopFileGuid
, sizeof (EFI_GUID
));
1671 FileHeader
->Type
= EFI_FV_FILETYPE_RAW
;
1672 FileHeader
->Attributes
= FFS_ATTRIB_CHECKSUM
;
1675 // Now FileSize includes the EFI_FFS_FILE_HEADER
1677 FileHeader
->Size
[0] = (UINT8
) (TotalVtfSize
& 0x000000FF);
1678 FileHeader
->Size
[1] = (UINT8
) ((TotalVtfSize
& 0x0000FF00) >> 8);
1679 FileHeader
->Size
[2] = (UINT8
) ((TotalVtfSize
& 0x00FF0000) >> 16);
1682 // Fill in checksums and state, all three must be zero for the checksums.
1684 FileHeader
->IntegrityCheck
.Checksum
.Header
= 0;
1685 FileHeader
->IntegrityCheck
.Checksum
.File
= 0;
1686 FileHeader
->State
= 0;
1687 FileHeader
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1688 FileHeader
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) (FileHeader
+ 1), TotalVtfSize
- sizeof (EFI_FFS_FILE_HEADER
));
1689 FileHeader
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1695 ValidateAddressAndSize (
1696 IN UINT64 BaseAddress
,
1701 Routine Description:
1703 Update the Firmware Volume Buffer with requested buffer data
1707 BaseAddress - Base address for the Fw Volume.
1709 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1713 EFI_SUCCESS - The function completed successfully
1714 EFI_UNSUPPORTED - The input parameter is error
1718 if ((BaseAddress
>= 0) && (FwVolSize
> 0x40) && ((BaseAddress
+ FwVolSize
) % 8 == 0)) {
1722 return EFI_UNSUPPORTED
;
1726 UpdateIA32ResetVector (
1728 IN UINT64 FirstFwVSize
1732 Routine Description:
1734 Update the 16 byte IA32 Reset vector to maintain the compatibility
1738 FileName - Binary file name which contains the IA32 Reset vector info..
1739 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
1743 EFI_SUCCESS - The function completed successfully
1744 EFI_ABORTED - Invalid File Size
1745 EFI_INVALID_PARAMETER - Bad File Name
1746 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1751 UINT8
*LocalVtfBuffer
;
1756 if (!strcmp (FileName
, "")) {
1757 return EFI_INVALID_PARAMETER
;
1760 Fp
= fopen (FileName
, "rb");
1763 Error (NULL
, 0, 0001, "Error opening file", FileName
);
1767 FileSize
= _filelength (fileno (Fp
));
1769 if (FileSize
> 16) {
1773 Buffer
= malloc (FileSize
);
1774 if (Buffer
== NULL
) {
1775 return EFI_OUT_OF_RESOURCES
;
1778 NumByteRead
= fread (Buffer
, sizeof (UINT8
), FileSize
, Fp
);
1780 LocalVtfBuffer
= (UINT8
*) Vtf1EndBuffer
- SIZE_IA32_RESET_VECT
;
1781 memcpy (LocalVtfBuffer
, Buffer
, FileSize
);
1799 Routine Description:
1801 This function cleans up any allocated buffer
1813 PARSED_VTF_INFO
*TempFileListPtr
;
1824 // Cleanup the buffer which was allocated to read the file names from FV.INF
1826 FileListPtr
= FileListHeadPtr
;
1827 while (FileListPtr
!= NULL
) {
1828 TempFileListPtr
= FileListPtr
->NextVtfInfo
;
1830 FileListPtr
= TempFileListPtr
;
1835 ProcessAndCreateVtf (
1840 Routine Description:
1842 This function process the link list created during INF file parsing
1843 and create component in VTF and updates its info in FIT table
1847 Size - Size of the Firmware Volume of which, this VTF belongs to.
1851 EFI_UNSUPPORTED - Unknown FIT type
1852 EFI_SUCCESS - The function completed successfully
1857 PARSED_VTF_INFO
*ParsedInfoPtr
;
1859 Status
= EFI_SUCCESS
;
1861 ParsedInfoPtr
= FileListHeadPtr
;
1863 while (ParsedInfoPtr
!= NULL
) {
1865 switch (ParsedInfoPtr
->CompType
) {
1867 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1869 case COMP_TYPE_FIT_HEADER
:
1870 //COMP_TYPE_FIT_HEADER 0x00
1871 Status
= CreateFitTableAndInitialize (ParsedInfoPtr
);
1875 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1877 case COMP_TYPE_FIT_PAL_A
:
1878 //COMP_TYPE_FIT_PAL_A 0x0F
1879 Status
= CreateAndUpdatePAL_A (ParsedInfoPtr
);
1882 // Based on VTF specification, once the PAL_A component has been written,
1883 // update the Firmware Volume info as FIT table. This will be utilized
1884 // to extract the Firmware Volume Start address where this VTF will be
1887 if (Status
== EFI_SUCCESS
) {
1888 UpdateFitEntryForFwVolume (Size
);
1892 case COMP_TYPE_FIT_FV_BOOT
:
1893 //COMP_TYPE_FIT_FV_BOOT 0x7E
1895 // Since FIT entry for Firmware Volume has been created and it is
1896 // located at (PAL_A start - 16 byte). So we will not process any
1897 // Firmware Volume related entry from INF file
1899 Status
= EFI_SUCCESS
;
1904 // Any other component type should be handled here. This will create the
1905 // image in specified VTF and create appropriate entry about this
1906 // component in FIT Entry.
1908 Status
= CreateAndUpdateComponent (ParsedInfoPtr
);
1909 if (EFI_ERROR (Status
)) {
1910 Error (NULL
, 0, 0002, "Error updating component", ParsedInfoPtr
->CompName
);
1916 ParsedInfoPtr
= ParsedInfoPtr
->NextVtfInfo
;
1923 IN UINT64 StartAddress1
,
1925 IN UINT64 StartAddress2
,
1931 Routine Description:
1933 This is the main function which will be called from application.
1937 StartAddress1 - The start address of the first VTF
1938 Size1 - The size of the first VTF
1939 StartAddress2 - The start address of the second VTF
1940 Size2 - The size of the second VTF
1941 fp - The pointer to BSF inf file
1945 EFI_OUT_OF_RESOURCES - Can not allocate memory
1946 The return value can be any of the values
1947 returned by the calls to following functions:
1948 GetVtfRelatedInfoFromInfFile
1950 UpdateIA32ResetVector
1959 Status
= EFI_UNSUPPORTED
;
1962 if (StartAddress2
== 0) {
1968 Fv1BaseAddress
= StartAddress1
;
1969 Fv1EndAddress
= Fv1BaseAddress
+ Size1
;
1970 if (Fv1EndAddress
!= 0x100000000ULL
|| Size1
< 0x100000) {
1971 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1972 if (Size1
< 0x100000) {
1973 Error (NULL
, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
1974 } else if (SecondVTF
!= TRUE
) {
1975 Error (NULL
, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
1978 return EFI_INVALID_PARAMETER
;
1982 // The image buffer for the First VTF
1984 Vtf1Buffer
= malloc ((UINTN
) Size1
);
1985 if (Vtf1Buffer
== NULL
) {
1986 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
1987 return EFI_OUT_OF_RESOURCES
;
1989 memset (Vtf1Buffer
, 0x00, (UINTN
) Size1
);
1990 Vtf1EndBuffer
= (UINT8
*) Vtf1Buffer
+ Size1
;
1991 Vtf1LastStartAddress
= Fv1EndAddress
| IPF_CACHE_BIT
;
1994 Fv2BaseAddress
= StartAddress2
;
1995 Fv2EndAddress
= Fv2BaseAddress
+ Size2
;
1996 if (Fv2EndAddress
!= StartAddress1
) {
1997 Error (NULL
, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1998 if (SecondVTF
== TRUE
) {
1999 Error (NULL
, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
2000 Error (NULL
, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
2003 return EFI_INVALID_PARAMETER
;
2007 // The image buffer for the second VTF
2009 Vtf2Buffer
= malloc ((UINTN
) Size2
);
2010 if (Vtf2Buffer
== NULL
) {
2011 Error (NULL
, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2012 return EFI_OUT_OF_RESOURCES
;
2014 memset (Vtf2Buffer
, 0x00, (UINTN
) Size2
);
2015 Vtf2EndBuffer
= (UINT8
*) Vtf2Buffer
+ Size2
;
2016 Vtf2LastStartAddress
= Fv2EndAddress
| IPF_CACHE_BIT
;
2019 Status
= GetVtfRelatedInfoFromInfFile (VtfFP
);
2021 if (Status
!= EFI_SUCCESS
) {
2022 Error (NULL
, 0, 0003, "Error parsing file", "the input file.");
2027 Status
= ProcessAndCreateVtf (Size1
);
2028 if (Status
!= EFI_SUCCESS
) {
2033 if (SectionOptionFlag
) {
2034 Status
= UpdateIA32ResetVector (IA32BinFile
, Vtf1TotalSize
);
2035 if (Status
!= EFI_SUCCESS
) {
2042 // Re arrange the FIT Table for Ascending order of their FIT Type..
2047 // All components have been updated in FIT table. Now perform the FIT table
2048 // checksum. The following function will check if Checksum is required,
2049 // if yes, then it will perform the checksum otherwise not.
2051 CalculateFitTableChecksum ();
2054 // Write the FFS header
2056 Vtf1TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2057 Vtf1LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2059 Status
= UpdateFfsHeader (Vtf1TotalSize
, FIRST_VTF
);
2060 if (Status
!= EFI_SUCCESS
) {
2065 // Update the VTF buffer into specified VTF binary file
2067 Status
= WriteVtfBinary (OutFileName1
, Vtf1TotalSize
, FIRST_VTF
);
2070 Vtf2TotalSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2071 Vtf2LastStartAddress
-= sizeof (EFI_FFS_FILE_HEADER
);
2072 Status
= UpdateFfsHeader (Vtf2TotalSize
, SECOND_VTF
);
2073 if (Status
!= EFI_SUCCESS
) {
2079 // Update the VTF buffer into specified VTF binary file
2081 Status
= WriteVtfBinary (OutFileName2
, Vtf2TotalSize
, SECOND_VTF
);
2090 PeimFixupInFitTable (
2091 IN UINT64 StartAddress
2095 Routine Description:
2097 This function is an entry point to fixup SAL-E entry point.
2101 StartAddress - StartAddress for PEIM.....
2105 EFI_SUCCESS - The function completed successfully
2106 EFI_ABORTED - Error Opening File
2107 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2113 UINT64
*StartAddressPtr
;
2117 StartAddressPtr
= malloc (sizeof (UINT64
));
2118 if (StartAddressPtr
== NULL
) {
2119 return EFI_OUT_OF_RESOURCES
;
2121 *StartAddressPtr
= StartAddress
;
2123 Fp
= fopen (OutFileName1
, "rb");
2126 Error (NULL
, 0, 0001, "Error opening file", OutFileName1
);
2127 if (StartAddressPtr
) {
2128 free (StartAddressPtr
);
2133 FirstFwVSize
= _filelength (fileno (Fp
));
2134 fseek (Fp
, (long) (FirstFwVSize
- (UINTN
) (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
)), SEEK_SET
);
2135 NumByte
= fwrite ((VOID
*) StartAddressPtr
, sizeof (UINT64
), 1, Fp
);
2141 if (StartAddressPtr
) {
2142 free (StartAddressPtr
);
2145 Status
= EFI_SUCCESS
;
2151 IN UINT64 BaseAddress
,
2152 IN CHAR8
*DestFileName
,
2153 IN CHAR8
*SourceFileName
,
2159 Routine Description:
2161 This function adds the SYM tokens in the source file to the destination file.
2162 The SYM tokens are updated to reflect the base address.
2166 BaseAddress - The base address for the new SYM tokens.
2167 DestFileName - The destination file.
2168 SourceFileName - The source file.
2169 FileSize - Size of bin file.
2173 EFI_SUCCESS - The function completed successfully.
2174 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2175 EFI_ABORTED - An error occurred.
2181 CHAR8 Buffer
[_MAX_PATH
];
2182 CHAR8 Type
[_MAX_PATH
];
2183 CHAR8 Address
[_MAX_PATH
];
2184 CHAR8 Section
[_MAX_PATH
];
2185 CHAR8 Token
[_MAX_PATH
];
2186 CHAR8 BaseToken
[_MAX_PATH
];
2187 UINT64 TokenAddress
;
2191 // Verify input parameters.
2193 if (BaseAddress
== 0 || DestFileName
== NULL
|| SourceFileName
== NULL
) {
2194 return EFI_INVALID_PARAMETER
;
2198 // Open the source file
2200 SourceFile
= fopen (SourceFileName
, "r");
2201 if (SourceFile
== NULL
) {
2204 // SYM files are not required.
2210 // Use the file name minus extension as the base for tokens
2212 strcpy (BaseToken
, SourceFileName
);
2213 strtok (BaseToken
, ". \t\n");
2214 strcat (BaseToken
, "__");
2217 // Open the destination file
2219 DestFile
= fopen (DestFileName
, "a+");
2220 if (DestFile
== NULL
) {
2221 fclose (SourceFile
);
2222 Error (NULL
, 0, 0001, "Error opening file", DestFileName
);
2227 // If this is the beginning of the output file, write the symbol format info.
2229 if (fseek (DestFile
, 0, SEEK_END
) != 0) {
2230 fclose (SourceFile
);
2232 Error (NULL
, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2236 StartLocation
= ftell (DestFile
);
2238 if (StartLocation
== 0) {
2239 fprintf (DestFile
, "TEXTSYM format | V1.0\n");
2240 } else if (StartLocation
== -1) {
2241 fclose (SourceFile
);
2243 Error (NULL
, 0, 2000, "Invalid parameter", "StartLocation error");
2248 // Read the first line
2250 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
2255 // Make sure it matches the expected sym format
2257 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
2258 fclose (SourceFile
);
2260 Error (NULL
, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2267 while (feof (SourceFile
) == 0) {
2272 if (fscanf (SourceFile
, "%s | %s | %s | %s\n", Type
, Address
, Section
, Token
) == 4) {
2275 // Get the token address
2277 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
2278 if (TokenAddress
> FileSize
) {
2280 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2286 // Add the base address, the size of the FFS file header and the size of the peim header.
2288 TokenAddress
+= BaseAddress
&~IPF_CACHE_BIT
;
2290 fprintf (DestFile
, "%s | %016llX | ", Type
, (unsigned long long) TokenAddress
);
2291 fprintf (DestFile
, "%s | %s\n %s\n", Section
, Token
, BaseToken
);
2295 fclose (SourceFile
);
2301 CalculateFitTableChecksum (
2306 Routine Description:
2308 This function will perform byte checksum on the FIT table, if the the checksum required
2309 field is set to CheckSum required. If the checksum is not required then checksum byte
2310 will have value as 0;.
2318 Status - Value returned by call to CalculateChecksum8 ()
2319 EFI_SUCCESS - The function completed successfully
2323 FIT_TABLE
*TmpFitPtr
;
2325 UINT64 FitTableAddOffset
;
2326 UINTN RelativeAddress
;
2330 // Read the Fit Table address from Itanium-based address map.
2332 FitTableAddOffset
= Fv1EndAddress
- (SIZE_IA32_RESET_VECT
+ SIZE_SALE_ENTRY_POINT
+ SIZE_FIT_TABLE_ADD
);
2335 // Translate this Itanium-based address in terms of local buffer address which
2336 // contains the image for Boot Strapped File
2338 GetRelativeAddressInVtfBuffer (FitTableAddOffset
, &RelativeAddress
, FIRST_VTF
);
2339 FitTableAdd
= *(UINTN
*) RelativeAddress
;
2341 GetRelativeAddressInVtfBuffer (FitTableAdd
, &RelativeAddress
, FIRST_VTF
);
2343 TmpFitPtr
= (FIT_TABLE
*) RelativeAddress
;
2345 Size
= TmpFitPtr
->CompSize
* 16;
2347 if ((TmpFitPtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2348 TmpFitPtr
->CheckSum
= 0;
2349 TmpFitPtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) TmpFitPtr
, Size
);
2351 TmpFitPtr
->CheckSum
= 0;
2363 Routine Description:
2365 Displays the standard utility information to SDTOUT
2377 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
2386 Routine Description:
2388 Displays the utility usage syntax to STDOUT
2403 fprintf (stdout
, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME
);
2406 // Copyright declaration
2408 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
2412 fprintf (stdout
, "Options:\n");
2413 fprintf (stdout
, " -f Input_file, --filename Input_file\n\
2414 Input_file is name of the BS Image INF file\n");
2415 fprintf (stdout
, " -r BaseAddress, --baseaddr BaseAddress\n\
2416 BaseAddress is the starting address of Firmware Volume\n\
2417 where Boot Strapped Image will reside.\n");
2418 fprintf (stdout
, " -s FwVolumeSize, --size FwVolumeSize\n\
2419 FwVolumeSize is the size of Firmware Volume.\n");
2420 fprintf (stdout
, " -o FileName, --output FileName\n\
2421 File will be created to store the ouput content.\n");
2422 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
2423 fprintf (stdout
, " --version Show program's version number and exit.\n");
2424 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
2425 fprintf (stdout
, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
2426 fprintf (stdout
, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
2436 Routine Description:
2438 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2439 part of firmware volume image.
2443 argc - The count of the parameters
2444 argv - The parameters
2449 0 - No error conditions detected.
2450 1 - One or more of the input parameters is invalid.
2451 2 - A resource required by the utility was unavailable.
2452 - Most commonly this will be memory allocation or file creation.
2453 3 - GenFvImage.dll could not be loaded.
2454 4 - Error executing the GenFvImage dll.
2455 5 - Now this tool does not support the IA32 platform
2460 UINT64 StartAddress1
;
2461 UINT64 StartAddress2
;
2464 BOOLEAN FirstRoundO
;
2465 BOOLEAN FirstRoundB
;
2466 BOOLEAN FirstRoundS
;
2471 SetUtilityName (UTILITY_NAME
);
2474 // Initialize variables
2484 OutFileName1
= NULL
;
2485 OutFileName2
= NULL
;
2490 // Verify the correct number of arguments
2497 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
2502 if ((strcmp(argv
[1], "--version") == 0)) {
2508 // Parse the command line arguments
2510 for (Index
= 1; Index
< argc
; Index
+= 2) {
2511 if ((stricmp (argv
[Index
], "-o") == 0) || (stricmp (argv
[Index
], "--output") == 0)) {
2512 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2513 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
2517 // Get the output file name
2522 // It's the first output file name
2524 OutFileName1
= (CHAR8
*)argv
[Index
+1];
2525 FirstRoundO
= FALSE
;
2528 //It's the second output file name
2530 OutFileName2
= (CHAR8
*)argv
[Index
+1];
2535 if ((stricmp (argv
[Index
], "-f") == 0) || (stricmp (argv
[Index
], "--filename") == 0)) {
2536 if (argv
[Index
+ 1] == NULL
|| argv
[Index
+ 1][0] == '-') {
2537 Error (NULL
, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
2541 // Get the input VTF file name
2543 VtfFileName
= argv
[Index
+1];
2544 VtfFP
= fopen(VtfFileName
, "rb");
2545 if (VtfFP
== NULL
) {
2546 Error (NULL
, 0, 0001, "Error opening file", VtfFileName
);
2552 if ((stricmp (argv
[Index
], "-r") == 0) || (stricmp (argv
[Index
], "--baseaddr") == 0)) {
2554 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress1
);
2555 FirstRoundB
= FALSE
;
2557 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &StartAddress2
);
2559 if (Status
!= EFI_SUCCESS
) {
2560 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv
[Index
+ 1]);
2566 if ((stricmp (argv
[Index
], "-s") == 0) || (stricmp (argv
[Index
], "--size") == 0)) {
2568 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize1
);
2569 FirstRoundS
= FALSE
;
2571 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &FwVolSize2
);
2575 if (Status
!= EFI_SUCCESS
) {
2576 Error (NULL
, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv
[Index
+ 1]);
2582 if ((stricmp (argv
[Index
], "-v") == 0) || (stricmp (argv
[Index
], "--verbose") == 0)) {
2588 if ((stricmp (argv
[Index
], "-q") == 0) || (stricmp (argv
[Index
], "--quiet") == 0)) {
2594 if ((stricmp (argv
[Index
], "-d") == 0) || (stricmp (argv
[Index
], "--debug") == 0)) {
2596 // debug level specified
2598 Status
= AsciiStringToUint64(argv
[Index
+ 1], FALSE
, &DebugLevel
);
2599 if (EFI_ERROR (Status
)) {
2600 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[Index
], argv
[Index
+ 1]);
2603 if (DebugLevel
> 9) {
2604 Error (NULL
, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv
[Index
+ 1]);
2607 if((DebugLevel
<= 9) &&(DebugLevel
>= 5)) {
2615 Error (NULL
, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv
[Index
]);
2619 if (VtfFP
== NULL
) {
2620 Error (NULL
, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2625 Error (NULL
, 0, 2000, "Invalid parameter", "No FV base address is specified");
2630 Error (NULL
, 0, 2000, "Invalid parameter", "No FV Size is specified");
2634 // All Parameters has been parsed, now set the message print level
2638 } else if (VerboseMode
) {
2640 } else if (DebugMode
) {
2641 SetPrintLevel(DebugLevel
);
2645 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
2648 if (VTF_OUTPUT
== FALSE
) {
2649 if (SecondVTF
== TRUE
) {
2650 OutFileName1
= VTF_OUTPUT_FILE1
;
2651 OutFileName2
= VTF_OUTPUT_FILE2
;
2653 OutFileName1
= VTF_OUTPUT_FILE1
;
2655 SymFileName
= VTF_SYM_FILE
;
2657 INTN OutFileNameLen
= strlen(OutFileName1
);
2660 for (Index
= OutFileNameLen
; Index
> 0; --Index
) {
2661 if (OutFileName1
[Index
] == '/' || OutFileName1
[Index
] == '\\') {
2666 SymFileName
= VTF_SYM_FILE
;
2668 INTN SymFileNameLen
= Index
+ 1 + strlen(VTF_SYM_FILE
);
2669 SymFileName
= malloc(SymFileNameLen
+ 1);
2670 memcpy(SymFileName
, OutFileName1
, Index
+ 1);
2671 memcpy(SymFileName
+ Index
+ 1, VTF_SYM_FILE
, strlen(VTF_SYM_FILE
));
2672 SymFileName
[SymFileNameLen
] = '\0';
2675 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, SymFileName
, NULL
);
2680 // Call the GenVtfImage
2683 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Start to generate the VTF image\n", NULL
);
2685 Status
= GenerateVtfImage (StartAddress1
, FwVolSize1
, StartAddress2
, FwVolSize2
, VtfFP
);
2687 if (EFI_ERROR (Status
)) {
2690 case EFI_INVALID_PARAMETER
:
2691 Error (NULL
, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2695 Error (NULL
, 0, 3000, "Invalid", "Error detected while creating the file image.");
2698 case EFI_OUT_OF_RESOURCES
:
2699 Error (NULL
, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2702 case EFI_VOLUME_CORRUPTED
:
2703 Error (NULL
, 0, 3000, "Invalid", "No base address was specified.");
2707 Error (NULL
, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status
);
2712 if (VtfFP
!= NULL
) {
2717 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "VTF image generated successful\n", NULL
);
2721 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2723 return GetUtilityStatus();