]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenVtf/GenVtf.c
035c268a2ca77989d9260284c390ac91cf63172f
[mirror_edk2.git] / BaseTools / Source / C / GenVtf / GenVtf.c
1 /**
2
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
8
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.
11
12
13 Module Name:
14
15 GenVtf.c
16
17 Abstract:
18
19 This file contains functions required to generate a boot strap file (BSF)
20 also known as the Volume Top File (VTF)
21
22 **/
23
24 //
25 //
26 //
27 #include <FvLib.h>
28 #include <Common/UefiBaseTypes.h>
29 #include "GenVtf.h"
30 #include <Guid/PiFirmwareFileSystem.h>
31 #include "CommonLib.h"
32 #include "EfiUtilityMsgs.h"
33
34 //
35 // Global variables
36 //
37 UINTN SectionOptionFlag = 0;
38 UINTN SectionCompFlag = 0;
39
40 UINT64 DebugLevel;
41 BOOLEAN DebugMode;
42
43 BOOLEAN QuietMode = FALSE;
44
45 BOOLEAN VTF_OUTPUT = FALSE;
46 CHAR8 *OutFileName1;
47 CHAR8 *OutFileName2;
48 CHAR8 *SymFileName;
49
50 CHAR8 **TokenStr;
51 CHAR8 **OrgStrTokPtr;
52
53 PARSED_VTF_INFO *FileListPtr;
54 PARSED_VTF_INFO *FileListHeadPtr;
55
56 VOID *Vtf1Buffer;
57 VOID *Vtf1EndBuffer;
58 VOID *Vtf2Buffer;
59 VOID *Vtf2EndBuffer;
60
61 UINTN ValidLineNum = 0;
62 UINTN ValidFFDFileListNum = 0;
63
64 //
65 // Section Description and their number of occurences in *.INF file
66 //
67 UINTN NumFvFiles = 0;
68 UINTN SectionOptionNum = 0;
69
70 //
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
73 //
74 BOOLEAN VTFPresent = FALSE;
75 BOOLEAN SecondVTF = FALSE;
76
77 //
78 // Address related information
79 //
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;
88
89 UINT32 BufferToTop = 0;
90
91 //
92 // IA32 Reset Vector Bin name
93 //
94 CHAR8 IA32BinFile[FILE_NAME_SIZE];
95
96 //
97 // Function Implementations
98 //
99 EFI_STATUS
100 ConvertVersionInfo (
101 IN CHAR8 *Str,
102 IN OUT UINT8 *MajorVer,
103 IN OUT UINT8 *MinorVer
104 )
105 /*++
106 Routine Description:
107
108 This function split version to major version and minor version
109
110 Arguments:
111
112 Str - String representing in form XX.XX
113 MajorVer - The major version
114 MinorVer - The minor version
115
116 Returns:
117
118 EFI_SUCCESS - The function completed successfully.
119
120 --*/
121 {
122 CHAR8 TemStr[5] = "0000";
123 unsigned Major;
124 unsigned Minor;
125 UINTN Length;
126
127 Major = 0;
128 Minor = 0;
129
130 if (strstr (Str, ".") != NULL) {
131 sscanf (
132 Str,
133 "%02x.%02x",
134 &Major,
135 &Minor
136 );
137 } else {
138 Length = strlen(Str);
139 if (Length < 4) {
140 strncpy (TemStr + 4 - Length, Str, Length);
141 } else {
142 strncpy (TemStr, Str + Length - 4, 4);
143 }
144
145 sscanf (
146 TemStr,
147 "%02x%02x",
148 &Major,
149 &Minor
150 );
151 }
152
153 *MajorVer = (UINT8) Major;
154 *MinorVer = (UINT8) Minor;
155 return EFI_SUCCESS;
156 }
157
158 VOID
159 TrimLine (
160 IN CHAR8 *Line
161 )
162 /*++
163 Routine Description:
164
165 This function cleans up the line by removing all whitespace and
166 comments
167
168 Arguments:
169
170 Line - The pointer of the string
171
172 Returns:
173
174 None
175
176 --*/
177 {
178 CHAR8 TmpLine[FILE_NAME_SIZE];
179 CHAR8 Char;
180 CHAR8 *Ptr0;
181 UINTN Index;
182 UINTN Index2;
183
184 //
185 // Change '#' to '//' for Comment style
186 //
187 if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {
188 Line[Ptr0 - Line] = 0;
189 }
190
191 //
192 // Initialize counters
193 //
194 Index = 0;
195 Index2 = 0;
196
197 while ((Char = Line[Index]) != 0) {
198 if ((Char != ' ') && (Char != '\t') && (Char != '\n') && (Char != '\r')) {
199 TmpLine[Index2++] = Char;
200 }
201 Index++;
202 }
203
204 TmpLine[Index2] = 0;
205 strcpy (Line, TmpLine);
206 }
207
208 VOID
209 ValidLineCount (
210 IN FILE *Fp
211 )
212 /*++
213
214 Routine Description:
215
216 This function calculated number of valid lines in a input file.
217
218 Arguments:
219
220 Fp - Pointer to a file handle which has been opened.
221
222 Returns:
223
224 None
225
226 --*/
227 {
228 CHAR8 Buff[FILE_NAME_SIZE];
229 while (fgets(Buff, sizeof (Buff), Fp)) {
230 TrimLine (Buff);
231 if (Buff[0] == 0) {
232 continue;
233 }
234 ValidLineNum++;
235 }
236 }
237
238 EFI_STATUS
239 ParseInputFile (
240 IN FILE *Fp
241 )
242 /*++
243
244 Routine Description:
245
246 This function parses the input file and tokenize the string
247
248 Arguments:
249
250 Fp - Pointer to a file handle which has been opened.
251
252 Returns:
253
254 None
255
256 --*/
257 {
258 CHAR8 *Token;
259 CHAR8 Buff[FILE_NAME_SIZE + 1];
260 CHAR8 Delimit[] = "=";
261
262 Buff [FILE_NAME_SIZE] = '\0';
263 Token = NULL;
264
265 while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) {
266 TrimLine (Buff);
267 if (Buff[0] == 0) {
268 continue;
269 }
270 Token = strtok (Buff, Delimit);
271 while (Token != NULL) {
272 strcpy (*TokenStr, Token);
273 TokenStr ++;
274 Token = strtok (NULL, Delimit);
275 }
276 }
277 return EFI_SUCCESS;
278 }
279
280 EFI_STATUS
281 InitializeComps (
282 VOID
283 )
284 /*++
285
286 Routine Description:
287
288 This function initializes the relevant global variable which is being
289 used to store the information retrieved from INF file. This also initializes
290 the VTF symbol file.
291
292 Arguments:
293
294 None
295
296 Returns:
297
298 EFI_SUCCESS - The function completed successfully
299 EFI_OUT_OF_RESOURCES - Malloc failed.
300
301 --*/
302 {
303
304 FileListPtr = malloc (sizeof (PARSED_VTF_INFO));
305
306 if (FileListPtr == NULL) {
307 return EFI_OUT_OF_RESOURCES;
308 }
309
310 FileListHeadPtr = FileListPtr;
311 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
312 FileListPtr->NextVtfInfo = NULL;
313
314 remove (SymFileName);
315 return EFI_SUCCESS;
316 }
317
318 VOID
319 ParseAndUpdateComponents (
320 IN PARSED_VTF_INFO *VtfInfo
321 )
322 /*++
323
324 Routine Description:
325
326 This function initializes the relevant global variable which is being
327 used to store the information retrieved from INF file.
328
329 Arguments:
330
331 VtfInfo - A pointer to the VTF Info Structure
332
333
334 Returns:
335
336 None
337
338 --*/
339 {
340 UINT64 StringValue;
341
342 while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) {
343
344 if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) {
345 TokenStr++;
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;
350 } else {
351 VtfInfo->LocationType = NONE;
352 }
353 } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) {
354 TokenStr++;
355 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
356 Error (NULL, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr);
357 return ;
358 }
359
360 VtfInfo->CompType = (UINT8) StringValue;
361 } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) {
362 TokenStr++;
363 if (strnicmp (*TokenStr, "-", 1) == 0) {
364 VtfInfo->VersionPresent = FALSE;
365 VtfInfo->MajorVer = 0;
366 VtfInfo->MinorVer = 0;
367 } else {
368 VtfInfo->VersionPresent = TRUE;
369 ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer);
370 }
371 } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) {
372 TokenStr++;
373 strcpy (VtfInfo->CompBinName, *TokenStr);
374 } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) {
375 TokenStr++;
376 strcpy (VtfInfo->CompSymName, *TokenStr);
377 } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) {
378 TokenStr++;
379 if (strnicmp (*TokenStr, "-", 1) == 0) {
380 VtfInfo->PreferredSize = FALSE;
381 VtfInfo->CompSize = 0;
382 } else {
383 VtfInfo->PreferredSize = TRUE;
384 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
385 Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr);
386 return ;
387 }
388
389 VtfInfo->CompSize = (UINTN) StringValue;
390 }
391
392 } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) {
393 TokenStr++;
394 if (strnicmp (*TokenStr, "1", 1) == 0) {
395 VtfInfo->CheckSumRequired = 1;
396 } else if (strnicmp (*TokenStr, "0", 1) == 0) {
397 VtfInfo->CheckSumRequired = 0;
398 } else {
399 Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
400 }
401 }
402
403 TokenStr++;
404 if (*TokenStr == NULL) {
405 break;
406 }
407 }
408 }
409
410 VOID
411 InitializeInFileInfo (
412 VOID
413 )
414 /*++
415
416 Routine Description:
417
418 This function intializes the relevant global variable which is being
419 used to store the information retrieved from INF file.
420
421 Arguments:
422
423 NONE
424
425 Returns:
426
427 NONE
428
429 --*/
430 {
431
432 SectionOptionFlag = 0;
433 SectionCompFlag = 0;
434 TokenStr = OrgStrTokPtr;
435
436 while (*TokenStr != NULL) {
437 if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) {
438 SectionOptionFlag = 1;
439 SectionCompFlag = 0;
440 }
441
442 if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 0) {
443 if (FileListPtr == NULL) {
444 FileListPtr = FileListHeadPtr;
445 }
446
447 SectionCompFlag = 1;
448 SectionOptionFlag = 0;
449 TokenStr++;
450 }
451
452 if (SectionOptionFlag) {
453 if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
454 TokenStr++;
455 strcpy (IA32BinFile, *TokenStr);
456 }
457 }
458
459 if (SectionCompFlag) {
460 if (stricmp (*TokenStr, "COMP_NAME") == 0) {
461 TokenStr++;
462 strcpy (FileListPtr->CompName, *TokenStr);
463 TokenStr++;
464 ParseAndUpdateComponents (FileListPtr);
465 }
466
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);
471 break;
472 }
473 FileListPtr = FileListPtr->NextVtfInfo;
474 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
475 FileListPtr->NextVtfInfo = NULL;
476 continue;
477 } else {
478 break;
479 }
480 }
481
482 TokenStr++;
483 }
484 }
485
486 EFI_STATUS
487 GetVtfRelatedInfoFromInfFile (
488 IN FILE *FilePointer
489 )
490 /*++
491
492 Routine Description:
493
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
496
497 Arguments:
498
499 FileName - FileName which needed to be read to parse data
500
501 Returns:
502
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
507
508 --*/
509 {
510 FILE *Fp;
511 UINTN Index;
512 UINTN Index1;
513 EFI_STATUS Status;
514
515 Status = EFI_SUCCESS;
516 Fp = FilePointer;
517 if (Fp == NULL) {
518 Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
519 return EFI_ABORTED;
520 }
521
522 ValidLineCount (Fp);
523
524 if (ValidLineNum == 0) {
525 Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
526 return EFI_INVALID_PARAMETER;
527 }
528
529 TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
530
531 if (TokenStr == NULL) {
532 return EFI_OUT_OF_RESOURCES;
533 }
534
535 memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
536 OrgStrTokPtr = TokenStr;
537
538 for (Index = 0; Index < (2 * ValidLineNum); Index++) {
539 *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
540
541 if (*TokenStr == NULL) {
542 Status = EFI_OUT_OF_RESOURCES;
543 goto ParseFileError;
544 }
545
546 memset (*TokenStr, 0, FILE_NAME_SIZE);
547 TokenStr++;
548 }
549
550 TokenStr = OrgStrTokPtr;
551 fseek (Fp, 0L, SEEK_SET);
552
553 Status = InitializeComps ();
554
555 if (Status != EFI_SUCCESS) {
556 goto ParseFileError;
557 }
558
559 Status = ParseInputFile (Fp);
560 if (Status != EFI_SUCCESS) {
561 goto ParseFileError;
562 }
563
564 InitializeInFileInfo ();
565
566 ParseFileError:
567
568 for (Index1 = 0; Index1 < Index; Index1 ++) {
569 free (OrgStrTokPtr[Index1]);
570 }
571
572 free (OrgStrTokPtr);
573
574 return Status;
575 }
576
577 VOID
578 GetRelativeAddressInVtfBuffer (
579 IN UINT64 Address,
580 IN OUT UINTN *RelativeAddress,
581 IN LOC_TYPE LocType
582 )
583 /*++
584
585 Routine Description:
586
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.
591
592 Arguments:
593
594 Address - The address of the flash map space
595 RelativeAddress - The relative address of the Buffer
596 LocType - The type of the VTF
597
598
599 Returns:
600
601
602 --*/
603 {
604 UINT64 TempAddress;
605 UINT8 *LocalBuff;
606
607 if (LocType == FIRST_VTF) {
608 LocalBuff = (UINT8 *) Vtf1EndBuffer;
609 TempAddress = Fv1EndAddress - Address;
610 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
611 } else {
612 LocalBuff = (UINT8 *) Vtf2EndBuffer;
613 TempAddress = Fv2EndAddress - Address;
614 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
615 }
616 }
617
618 EFI_STATUS
619 GetComponentVersionInfo (
620 IN OUT PARSED_VTF_INFO *VtfInfo,
621 IN UINT8 *Buffer
622 )
623 /*++
624 Routine Description:
625
626 This function will extract the version information from File
627
628 Arguments:
629
630 VtfInfo - A Pointer to the VTF Info Structure
631 Buffer - A Pointer to type UINT8
632
633 Returns:
634
635 EFI_SUCCESS - The function completed successfully
636 EFI_INVALID_PARAMETER - The parameter is invalid
637
638 --*/
639 {
640 UINT16 VersionInfo;
641 EFI_STATUS Status;
642
643 switch (VtfInfo->CompType) {
644
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;
651 break;
652
653 default:
654 Status = EFI_INVALID_PARAMETER;
655 break;
656 }
657
658 return Status;
659 }
660
661 BOOLEAN
662 CheckAddressAlignment (
663 IN UINT64 Address,
664 IN UINT64 AlignmentData,
665 IN OUT UINT64 *AlignAdjustByte
666 )
667 /*++
668
669 Routine Description:
670
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.
675
676 Arguments:
677
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.
681
682 Returns:
683
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.
687
688 --*/
689 {
690 //
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
693 // address boundary
694 //
695 *AlignAdjustByte = (Address % AlignmentData);
696
697 if (*AlignAdjustByte == 0) {
698 return TRUE;
699 } else {
700 return FALSE;
701 }
702 }
703
704 EFI_STATUS
705 GetFitTableStartAddress (
706 IN OUT FIT_TABLE **FitTable
707 )
708 /*++
709
710 Routine Description:
711
712 Get the FIT table start address in VTF Buffer
713
714 Arguments:
715
716 FitTable - Pointer to available fit table where new component can be added
717
718 Returns:
719
720 EFI_SUCCESS - The function completed successfully
721
722 --*/
723 {
724 UINT64 FitTableAdd;
725 UINT64 FitTableAddOffset;
726 UINTN RelativeAddress;
727
728 //
729 // Read the Fit Table address from Itanium-based address map.
730 //
731 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
732
733 //
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.
737 //
738 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
739 FitTableAdd = *(UINTN *) RelativeAddress;
740
741 //
742 // The FitTableAdd is the extracted Itanium based address pointing to FIT
743 // table. The relative address will return its actual location in VTF
744 // Buffer.
745 //
746 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
747
748 *FitTable = (FIT_TABLE *) RelativeAddress;
749
750 return EFI_SUCCESS;
751 }
752
753 EFI_STATUS
754 GetNextAvailableFitPtr (
755 IN FIT_TABLE **FitPtr
756 )
757 /*++
758
759 Routine Description:
760
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.
767
768 Arguments:
769
770 FitPtr - Pointer to available fit table where new component can be added
771
772 Returns:
773
774 EFI_SUCCESS - The function completed successfully
775
776 --*/
777 {
778 FIT_TABLE *TmpFitPtr;
779 UINT64 FitTableAdd;
780 UINT64 FitTableAddOffset;
781 UINTN Index;
782 UINTN NumFitComponents;
783 UINTN RelativeAddress;
784
785 //
786 // Read the Fit Table address from Itanium-based address map.
787 //
788 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
789
790 //
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.
794 //
795 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
796 FitTableAdd = *(UINTN *) RelativeAddress;
797
798 //
799 // The FitTableAdd is the extracted Itanium based address pointing to FIT
800 // table. The relative address will return its actual location in VTF
801 // Buffer.
802 //
803 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
804
805 TmpFitPtr = (FIT_TABLE *) RelativeAddress;
806 NumFitComponents = TmpFitPtr->CompSize;
807
808 for (Index = 0; Index < NumFitComponents; Index++) {
809 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {
810 *FitPtr = TmpFitPtr;
811 break;
812 }
813
814 TmpFitPtr++;
815 }
816
817 return EFI_SUCCESS;
818 }
819
820 int
821 CompareItems (
822 IN const VOID *Arg1,
823 IN const VOID *Arg2
824 )
825 /*++
826
827 Routine Description:
828
829 This function is used by qsort to sort the FIT table based upon Component
830 Type in their incresing order.
831
832 Arguments:
833
834 Arg1 - Pointer to Arg1
835 Arg2 - Pointer to Arg2
836
837 Returns:
838
839 None
840
841 --*/
842 {
843 if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
844 return 1;
845 } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
846 return -1;
847 } else {
848 return 0;
849 }
850 }
851
852 VOID
853 SortFitTable (
854 IN VOID
855 )
856 /*++
857
858 Routine Description:
859
860 This function is used by qsort to sort the FIT table based upon Component
861 Type in their incresing order.
862
863 Arguments:
864
865 VOID
866
867 Returns:
868
869 None
870
871 --*/
872 {
873 FIT_TABLE *FitTable;
874 FIT_TABLE *TmpFitPtr;
875 UINTN NumFitComponents;
876 UINTN Index;
877
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;
884 }
885 TmpFitPtr++;
886 }
887 qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);
888 }
889
890 VOID
891 UpdateFitEntryForFwVolume (
892 IN UINT64 Size
893 )
894 /*++
895
896 Routine Description:
897
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..
902
903
904 Arguments:
905
906 Size - Firmware Volume Size
907
908 Returns:
909
910 VOID
911
912 --*/
913 {
914 FIT_TABLE *CompFitPtr;
915 UINTN RelativeAddress;
916
917 //
918 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
919 //
920 Vtf1LastStartAddress -= 0x10;
921 Vtf1TotalSize += 0x10;
922
923 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
924
925 CompFitPtr = (FIT_TABLE *) RelativeAddress;
926 CompFitPtr->CompAddress = Fv1BaseAddress;
927
928 //
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
933 //
934 //
935 // Firmware Volume Size in 16 byte block
936 //
937 CompFitPtr->CompSize = ((UINT32) Size) / 16;
938
939 //
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.
943 //
944 CompFitPtr->CompVersion = MAKE_VERSION (0, 0);
945
946 //
947 // Since we don't have any info about this file, we are making sure that
948 // checksum is not needed.
949 //
950 CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);
951
952 //
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
957 // checksum
958 //
959 CompFitPtr->CheckSum = 0;
960 }
961
962 EFI_STATUS
963 UpdateFitEntryForNonVTFComp (
964 IN PARSED_VTF_INFO *VtfInfo
965 )
966 /*++
967
968 Routine Description:
969
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
973 FIT table.
974
975 Arguments:
976
977 VtfInfo - Pointer to VTF Info Structure
978
979 Returns:
980
981 EFI_ABORTED - The function fails to update the component in FIT
982 EFI_SUCCESS - The function completed successfully
983
984 --*/
985 {
986 FIT_TABLE *CompFitPtr;
987
988 //
989 // Scan the FIT table for available space
990 //
991 GetNextAvailableFitPtr (&CompFitPtr);
992 if (CompFitPtr == NULL) {
993 Error (NULL, 0, 5003, "Invalid", "Can't update this component in FIT");
994 return EFI_ABORTED;
995 }
996
997 //
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
1001 //
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);
1006
1007 //
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
1012 // checksum
1013 //
1014 CompFitPtr->CheckSum = 0;
1015
1016 //
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.
1019 //
1020 if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {
1021 CompFitPtr->CompAddress = Fv1BaseAddress;
1022 }
1023
1024 return EFI_SUCCESS;
1025 }
1026
1027 //
1028 // !!!WARNING
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
1035 //
1036 EFI_STATUS
1037 UpdateEntryPoint (
1038 IN PARSED_VTF_INFO *VtfInfo,
1039 IN UINT64 *CompStartAddress
1040 )
1041 /*++
1042
1043 Routine Description:
1044
1045 This function updated the architectural entry point in IPF, SALE_ENTRY.
1046
1047 Arguments:
1048
1049 VtfInfo - Pointer to VTF Info Structure
1050 CompStartAddress - Pointer to Component Start Address
1051
1052 Returns:
1053
1054 EFI_INVALID_PARAMETER - The parameter is invalid
1055 EFI_SUCCESS - The function completed successfully
1056
1057 --*/
1058 {
1059 UINTN RelativeAddress;
1060 UINT64 SalEntryAdd;
1061 FILE *Fp;
1062 UINTN Offset;
1063
1064 CHAR8 Buff[FILE_NAME_SIZE];
1065 CHAR8 Buff1[10];
1066 CHAR8 Buff2[10];
1067 CHAR8 OffsetStr[30];
1068 CHAR8 Buff3[10];
1069 CHAR8 Buff4[10];
1070 CHAR8 Buff5[10];
1071 CHAR8 Token[50];
1072
1073 Fp = fopen (VtfInfo->CompSymName, "rb");
1074
1075 if (Fp == NULL) {
1076 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName);
1077 return EFI_INVALID_PARAMETER;
1078 }
1079
1080 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
1081 fscanf (
1082 Fp,
1083 "%s %s %s %s %s %s %s",
1084 Buff1,
1085 Buff2,
1086 OffsetStr,
1087 Buff3,
1088 Buff4,
1089 Buff5,
1090 Token
1091 );
1092 if (strnicmp (Token, "SALE_ENTRY", 10) == 0) {
1093 break;
1094 }
1095 }
1096
1097 Offset = strtoul (OffsetStr, NULL, 16);
1098
1099 *CompStartAddress += Offset;
1100 SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
1101
1102 GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
1103
1104 memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
1105
1106 if (Fp != NULL) {
1107 fclose (Fp);
1108 }
1109
1110 return EFI_SUCCESS;
1111 }
1112
1113 EFI_STATUS
1114 CreateAndUpdateComponent (
1115 IN PARSED_VTF_INFO *VtfInfo
1116 )
1117 /*++
1118
1119 Routine Description:
1120
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
1124
1125 Arguments:
1126
1127 VtfInfo - Pointer to Parsed Info
1128
1129 Returns:
1130
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.
1135
1136 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1137 EFI_OUT_OF_RESOURCES Memory allocation failure.
1138
1139 --*/
1140 {
1141 EFI_STATUS Status;
1142 UINT64 CompStartAddress;
1143 UINT64 FileSize;
1144 UINT64 NumByteRead;
1145 UINT64 NumAdjustByte;
1146 UINT8 *Buffer;
1147 FILE *Fp;
1148 FIT_TABLE *CompFitPtr;
1149 BOOLEAN Aligncheck;
1150
1151 if (VtfInfo->LocationType == NONE) {
1152 UpdateFitEntryForNonVTFComp (VtfInfo);
1153 return EFI_SUCCESS;
1154 }
1155
1156 Fp = fopen (VtfInfo->CompBinName, "rb");
1157
1158 if (Fp == NULL) {
1159 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
1160 return EFI_ABORTED;
1161 }
1162
1163 FileSize = _filelength (fileno (Fp));
1164 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1165
1166 //
1167 // BUGBUG: Satish to correct
1168 //
1169 FileSize -= SIZE_OF_PAL_HEADER;
1170 }
1171
1172 if (VtfInfo->PreferredSize) {
1173 if (FileSize > VtfInfo->CompSize) {
1174 Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
1175 return EFI_ABORTED;
1176 }
1177
1178 FileSize = VtfInfo->CompSize;
1179 }
1180
1181 Buffer = malloc ((UINTN) FileSize);
1182 if (Buffer == NULL) {
1183 return EFI_OUT_OF_RESOURCES;
1184 }
1185 memset (Buffer, 0, (UINTN) FileSize);
1186
1187 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1188
1189 //
1190 // Read first 64 bytes of PAL header and use it to find version info
1191 //
1192 NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1193
1194 //
1195 // PAL header contains the version info. Currently, we will use the header
1196 // to read version info and then discard.
1197 //
1198 if (!VtfInfo->VersionPresent) {
1199 GetComponentVersionInfo (VtfInfo, Buffer);
1200 }
1201 }
1202
1203 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1204 fclose (Fp);
1205
1206 //
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.
1209 //
1210 if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
1211 if (!VtfInfo->VersionPresent) {
1212 GetComponentVersionInfo (VtfInfo, Buffer);
1213 }
1214 }
1215
1216 if (VtfInfo->LocationType == SECOND_VTF) {
1217
1218 CompStartAddress = (Vtf2LastStartAddress - FileSize);
1219 } else {
1220 CompStartAddress = (Vtf1LastStartAddress - FileSize);
1221 }
1222
1223 if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
1224 Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
1225 } else {
1226 Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
1227 }
1228
1229 if (!Aligncheck) {
1230 CompStartAddress -= NumAdjustByte;
1231 }
1232
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);
1241 } else {
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;
1244 }
1245
1246 if (EFI_ERROR (Status)) {
1247 return EFI_ABORTED;
1248 }
1249
1250 GetNextAvailableFitPtr (&CompFitPtr);
1251
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;
1256 }
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);
1264 }
1265
1266 //
1267 // Free the buffer
1268 //
1269 if (Buffer) {
1270 free (Buffer);
1271 }
1272
1273 //
1274 // Update the SYM file for this component based on it's start address.
1275 //
1276 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
1277 if (EFI_ERROR (Status)) {
1278
1279 //
1280 // At this time, SYM files are not required, so continue on error.
1281 //
1282 }
1283
1284 // !!!!!!!!!!!!!!!!!!!!!
1285 // BUGBUG:
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 // !!!!!!!!!!!!!!!!!!!!!!!
1290
1291 if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
1292 Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);
1293 }
1294
1295 return Status;
1296 }
1297
1298 EFI_STATUS
1299 CreateAndUpdatePAL_A (
1300 IN PARSED_VTF_INFO *VtfInfo
1301 )
1302 /*++
1303
1304 Routine Description:
1305
1306 This function reads the binary file for each components and update them
1307 in VTF Buffer as well as FIT table
1308
1309 Arguments:
1310
1311 VtfInfo - Pointer to Parsed Info
1312
1313 Returns:
1314
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.
1324
1325 --*/
1326 {
1327 EFI_STATUS Status;
1328 UINT64 PalStartAddress;
1329 UINT64 AbsAddress;
1330 UINTN RelativeAddress;
1331 UINT64 FileSize;
1332 UINT64 NumByteRead;
1333 UINT8 *Buffer;
1334 FILE *Fp;
1335 FIT_TABLE *PalFitPtr;
1336
1337 Fp = fopen (VtfInfo->CompBinName, "rb");
1338
1339 if (Fp == NULL) {
1340 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
1341 return EFI_ABORTED;
1342 }
1343
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;
1348 }
1349 FileSize -= SIZE_OF_PAL_HEADER;
1350
1351
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.");
1355 return EFI_ABORTED;
1356 }
1357
1358 FileSize = VtfInfo->CompSize;
1359 }
1360
1361 Buffer = malloc ((UINTN) FileSize);
1362 if (Buffer == NULL) {
1363 return EFI_OUT_OF_RESOURCES;
1364 }
1365 memset (Buffer, 0, (UINTN) FileSize);
1366
1367 //
1368 // Read, Get version Info and discard the PAL header.
1369 //
1370 NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1371
1372 //
1373 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1374 //
1375 if (!VtfInfo->VersionPresent) {
1376 GetComponentVersionInfo (VtfInfo, Buffer);
1377 }
1378
1379 //
1380 // Read PAL_A file in a buffer
1381 //
1382 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1383 fclose (Fp);
1384
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);
1389
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;
1398 }
1399
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);
1406 }
1407
1408 if (Buffer) {
1409 free (Buffer);
1410 }
1411
1412 //
1413 // Update the SYM file for this component based on it's start address.
1414 //
1415 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
1416 if (EFI_ERROR (Status)) {
1417
1418 //
1419 // At this time, SYM files are not required, so continue on error.
1420 //
1421 }
1422
1423 return Status;
1424 }
1425
1426 EFI_STATUS
1427 CreateFitTableAndInitialize (
1428 IN PARSED_VTF_INFO *VtfInfo
1429 )
1430 /*++
1431
1432 Routine Description:
1433
1434 This function creates and intializes FIT table which would be used to
1435 add component info inside this
1436
1437 Arguments:
1438
1439 VtfInfo - Pointer to Parsed Info
1440
1441 Returns:
1442
1443 EFI_ABORTED - Aborted due to no size information
1444 EFI_SUCCESS - The function completed successfully
1445
1446 --*/
1447 {
1448 UINT64 PalFitTableAdd;
1449 UINT64 FitTableAdd;
1450 UINT64 FitTableAddressOffset;
1451 FIT_TABLE *PalFitPtr;
1452 FIT_TABLE *FitStartPtr;
1453 UINTN NumFitComp;
1454 UINTN RelativeAddress;
1455 UINTN Index;
1456
1457 if (!VtfInfo->PreferredSize) {
1458 Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1459 return EFI_ABORTED;
1460 }
1461
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.");
1464 }
1465
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);
1470
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;
1475
1476 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
1477
1478 //
1479 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1480 //
1481 FitStartPtr = (FIT_TABLE *) RelativeAddress;
1482
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);
1487
1488 //
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
1492 // table
1493 //
1494 FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
1495
1496 NumFitComp = FitStartPtr->CompSize;
1497
1498 FitStartPtr++;
1499
1500 //
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.
1504 //
1505 for (Index = 0; Index < (NumFitComp - 1); Index++) {
1506 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED
1507 FitStartPtr++;
1508 }
1509
1510 Vtf1TotalSize += VtfInfo->CompSize;
1511 Vtf1LastStartAddress -= VtfInfo->CompSize;
1512
1513 return EFI_SUCCESS;
1514 }
1515
1516 EFI_STATUS
1517 WriteVtfBinary (
1518 IN CHAR8 *FileName,
1519 IN UINT32 VtfSize,
1520 IN LOC_TYPE LocType
1521 )
1522 /*++
1523
1524 Routine Description:
1525
1526 Write Firmware Volume from memory to a file.
1527
1528 Arguments:
1529
1530 FileName - Output File Name which needed to be created/
1531 VtfSize - FileSize
1532 LocType - The type of the VTF
1533
1534 Returns:
1535
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
1540
1541 --*/
1542 {
1543 FILE *Fp;
1544 UINTN NumByte;
1545 VOID *VtfBuffer;
1546 UINTN RelativeAddress;
1547
1548 if (LocType == FIRST_VTF) {
1549 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1550 VtfBuffer = (VOID *) RelativeAddress;
1551 } else {
1552 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1553 VtfBuffer = (VOID *) RelativeAddress;
1554 }
1555
1556 Fp = fopen (FileName, "wb");
1557 if (Fp == NULL) {
1558 Error (NULL, 0, 0001, "Error opening file", FileName);
1559 return EFI_ABORTED;
1560 }
1561
1562 NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);
1563
1564 if (Fp) {
1565 fclose (Fp);
1566 }
1567
1568 if (NumByte != (sizeof (UINT8) * VtfSize)) {
1569 Error (NULL, 0, 0002, "Error writing file", FileName);
1570 return EFI_ABORTED;
1571 }
1572
1573 return EFI_SUCCESS;
1574 }
1575
1576 EFI_STATUS
1577 UpdateVtfBuffer (
1578 IN UINT64 StartAddress,
1579 IN UINT8 *Buffer,
1580 IN UINT64 DataSize,
1581 IN LOC_TYPE LocType
1582 )
1583 /*++
1584
1585 Routine Description:
1586
1587 Update the Firmware Volume Buffer with requested buffer data
1588
1589 Arguments:
1590
1591 StartAddress - StartAddress in buffer. This number will automatically
1592 point to right address in buffer where data needed
1593 to be updated.
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
1597
1598 Returns:
1599
1600 EFI_ABORTED - The input parameter is error
1601 EFI_SUCCESS - The function completed successfully
1602
1603 --*/
1604 {
1605 UINT8 *LocalBufferPtrToWrite;
1606
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.");
1610 return EFI_ABORTED;
1611 }
1612
1613 LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;
1614
1615 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
1616
1617 } else {
1618
1619 if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {
1620 Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");
1621 return EFI_ABORTED;
1622 }
1623 LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;
1624 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
1625 }
1626
1627 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
1628
1629 return EFI_SUCCESS;
1630 }
1631
1632 EFI_STATUS
1633 UpdateFfsHeader (
1634 IN UINT32 TotalVtfSize,
1635 IN LOC_TYPE LocType
1636 )
1637 /*++
1638
1639 Routine Description:
1640
1641 Update the Firmware Volume Buffer with requested buffer data
1642
1643 Arguments:
1644
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
1648
1649 Returns:
1650
1651 EFI_SUCCESS - The function completed successfully
1652 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1653
1654 --*/
1655 {
1656 EFI_FFS_FILE_HEADER *FileHeader;
1657 UINTN RelativeAddress;
1658 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1659
1660 //
1661 // Find the VTF file header location
1662 //
1663 if (LocType == FIRST_VTF) {
1664 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1665 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1666 } else {
1667 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1668 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1669 }
1670
1671 if (FileHeader == NULL) {
1672 return EFI_INVALID_PARAMETER;
1673 }
1674
1675 //
1676 // write header
1677 //
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;
1682
1683 //
1684 // Now FileSize includes the EFI_FFS_FILE_HEADER
1685 //
1686 FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);
1687 FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);
1688 FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);
1689
1690 //
1691 // Fill in checksums and state, all three must be zero for the checksums.
1692 //
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;
1699
1700 return EFI_SUCCESS;
1701 }
1702
1703 EFI_STATUS
1704 ValidateAddressAndSize (
1705 IN UINT64 BaseAddress,
1706 IN UINT64 FwVolSize
1707 )
1708 /*++
1709
1710 Routine Description:
1711
1712 Update the Firmware Volume Buffer with requested buffer data
1713
1714 Arguments:
1715
1716 BaseAddress - Base address for the Fw Volume.
1717
1718 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1719
1720 Returns:
1721
1722 EFI_SUCCESS - The function completed successfully
1723 EFI_UNSUPPORTED - The input parameter is error
1724
1725 --*/
1726 {
1727 if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
1728 return EFI_SUCCESS;
1729 }
1730
1731 return EFI_UNSUPPORTED;
1732 }
1733
1734 EFI_STATUS
1735 UpdateIA32ResetVector (
1736 IN CHAR8 *FileName,
1737 IN UINT64 FirstFwVSize
1738 )
1739 /*++
1740
1741 Routine Description:
1742
1743 Update the 16 byte IA32 Reset vector to maintain the compatibility
1744
1745 Arguments:
1746
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..
1749
1750 Returns:
1751
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.
1756
1757 --*/
1758 {
1759 UINT8 *Buffer;
1760 UINT8 *LocalVtfBuffer;
1761 UINTN FileSize;
1762 UINTN NumByteRead;
1763 FILE *Fp;
1764
1765 if (!strcmp (FileName, "")) {
1766 return EFI_INVALID_PARAMETER;
1767 }
1768
1769 Fp = fopen (FileName, "rb");
1770
1771 if (Fp == NULL) {
1772 Error (NULL, 0, 0001, "Error opening file", FileName);
1773 return EFI_ABORTED;
1774 }
1775
1776 FileSize = _filelength (fileno (Fp));
1777
1778 if (FileSize > 16) {
1779 return EFI_ABORTED;
1780 }
1781
1782 Buffer = malloc (FileSize);
1783 if (Buffer == NULL) {
1784 return EFI_OUT_OF_RESOURCES;
1785 }
1786
1787 NumByteRead = fread (Buffer, sizeof (UINT8), FileSize, Fp);
1788
1789 LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;
1790 memcpy (LocalVtfBuffer, Buffer, FileSize);
1791
1792 if (Buffer) {
1793 free (Buffer);
1794 }
1795
1796 if (Fp != NULL) {
1797 fclose (Fp);
1798 }
1799 return EFI_SUCCESS;
1800 }
1801
1802 VOID
1803 CleanUpMemory (
1804 VOID
1805 )
1806 /*++
1807
1808 Routine Description:
1809
1810 This function cleans up any allocated buffer
1811
1812 Arguments:
1813
1814 NONE
1815
1816 Returns:
1817
1818 NONE
1819
1820 --*/
1821 {
1822 PARSED_VTF_INFO *TempFileListPtr;
1823
1824 if (Vtf1Buffer) {
1825 free (Vtf1Buffer);
1826 }
1827
1828 if (Vtf2Buffer) {
1829 free (Vtf2Buffer);
1830 }
1831
1832 //
1833 // Cleanup the buffer which was allocated to read the file names from FV.INF
1834 //
1835 FileListPtr = FileListHeadPtr;
1836 while (FileListPtr != NULL) {
1837 TempFileListPtr = FileListPtr->NextVtfInfo;
1838 free (FileListPtr);
1839 FileListPtr = TempFileListPtr;
1840 }
1841 }
1842
1843 EFI_STATUS
1844 ProcessAndCreateVtf (
1845 IN UINT64 Size
1846 )
1847 /*++
1848
1849 Routine Description:
1850
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
1853
1854 Arguments:
1855
1856 Size - Size of the Firmware Volume of which, this VTF belongs to.
1857
1858 Returns:
1859
1860 EFI_UNSUPPORTED - Unknown FIT type
1861 EFI_SUCCESS - The function completed successfully
1862
1863 --*/
1864 {
1865 EFI_STATUS Status;
1866 PARSED_VTF_INFO *ParsedInfoPtr;
1867
1868 Status = EFI_SUCCESS;
1869
1870 ParsedInfoPtr = FileListHeadPtr;
1871
1872 while (ParsedInfoPtr != NULL) {
1873
1874 switch (ParsedInfoPtr->CompType) {
1875 //
1876 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1877 //
1878 case COMP_TYPE_FIT_HEADER:
1879 //COMP_TYPE_FIT_HEADER 0x00
1880 Status = CreateFitTableAndInitialize (ParsedInfoPtr);
1881 break;
1882
1883 //
1884 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1885 //
1886 case COMP_TYPE_FIT_PAL_A:
1887 //COMP_TYPE_FIT_PAL_A 0x0F
1888 Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
1889
1890 //
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
1894 // of part.
1895 //
1896 if (Status == EFI_SUCCESS) {
1897 UpdateFitEntryForFwVolume (Size);
1898 }
1899 break;
1900
1901 case COMP_TYPE_FIT_FV_BOOT:
1902 //COMP_TYPE_FIT_FV_BOOT 0x7E
1903 //
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
1907 //
1908 Status = EFI_SUCCESS;
1909 break;
1910
1911 default:
1912 //
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.
1916 //
1917 Status = CreateAndUpdateComponent (ParsedInfoPtr);
1918 if (EFI_ERROR (Status)) {
1919 Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);
1920 return EFI_ABORTED;
1921 } else {
1922 break;}
1923 }
1924
1925 ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;
1926 }
1927 return Status;
1928 }
1929
1930 EFI_STATUS
1931 GenerateVtfImage (
1932 IN UINT64 StartAddress1,
1933 IN UINT64 Size1,
1934 IN UINT64 StartAddress2,
1935 IN UINT64 Size2,
1936 IN FILE *fp
1937 )
1938 /*++
1939
1940 Routine Description:
1941
1942 This is the main function which will be called from application.
1943
1944 Arguments:
1945
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
1951
1952 Returns:
1953
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
1958 ProcessAndCreateVtf
1959 UpdateIA32ResetVector
1960 UpdateFfsHeader
1961 WriteVtfBinary
1962
1963 --*/
1964 {
1965 EFI_STATUS Status;
1966 FILE *VtfFP;
1967
1968 Status = EFI_UNSUPPORTED;
1969 VtfFP = fp;
1970
1971 if (StartAddress2 == 0) {
1972 SecondVTF = FALSE;
1973 } else {
1974 SecondVTF = TRUE;
1975 }
1976
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!");
1985 }
1986 Usage();
1987 return EFI_INVALID_PARAMETER;
1988 }
1989
1990 //
1991 // The image buffer for the First VTF
1992 //
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;
1997 }
1998 memset (Vtf1Buffer, 0x00, (UINTN) Size1);
1999 Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1;
2000 Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
2001
2002 if (SecondVTF) {
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!");
2010 }
2011 Usage();
2012 return EFI_INVALID_PARAMETER;
2013 }
2014
2015 //
2016 // The image buffer for the second VTF
2017 //
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;
2022 }
2023 memset (Vtf2Buffer, 0x00, (UINTN) Size2);
2024 Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2;
2025 Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
2026 }
2027
2028 Status = GetVtfRelatedInfoFromInfFile (VtfFP);
2029
2030 if (Status != EFI_SUCCESS) {
2031 Error (NULL, 0, 0003, "Error parsing file", "the input file.");
2032 CleanUpMemory ();
2033 return Status;
2034 }
2035
2036 Status = ProcessAndCreateVtf (Size1);
2037 if (Status != EFI_SUCCESS) {
2038 CleanUpMemory ();
2039 return Status;
2040 }
2041
2042 if (SectionOptionFlag) {
2043 Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);
2044 if (Status != EFI_SUCCESS) {
2045 CleanUpMemory ();
2046 return Status;
2047 }
2048 }
2049
2050 //
2051 // Re arrange the FIT Table for Ascending order of their FIT Type..
2052 //
2053 SortFitTable ();
2054
2055 //
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.
2059 //
2060 CalculateFitTableChecksum ();
2061
2062 //
2063 // Write the FFS header
2064 //
2065 Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
2066 Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
2067
2068 Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);
2069 if (Status != EFI_SUCCESS) {
2070 CleanUpMemory ();
2071 return Status;
2072 }
2073 //
2074 // Update the VTF buffer into specified VTF binary file
2075 //
2076 Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);
2077
2078 if (SecondVTF) {
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) {
2083 CleanUpMemory ();
2084 return Status;
2085 }
2086
2087 //
2088 // Update the VTF buffer into specified VTF binary file
2089 //
2090 Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);
2091 }
2092
2093 CleanUpMemory ();
2094
2095 return Status;
2096 }
2097
2098 EFI_STATUS
2099 PeimFixupInFitTable (
2100 IN UINT64 StartAddress
2101 )
2102 /*++
2103
2104 Routine Description:
2105
2106 This function is an entry point to fixup SAL-E entry point.
2107
2108 Arguments:
2109
2110 StartAddress - StartAddress for PEIM.....
2111
2112 Returns:
2113
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.
2117
2118 --*/
2119 {
2120 EFI_STATUS Status;
2121 FILE *Fp;
2122 UINT64 *StartAddressPtr;
2123 UINTN FirstFwVSize;
2124 UINTN NumByte;
2125
2126 StartAddressPtr = malloc (sizeof (UINT64));
2127 if (StartAddressPtr == NULL) {
2128 return EFI_OUT_OF_RESOURCES;
2129 }
2130 *StartAddressPtr = StartAddress;
2131
2132 Fp = fopen (OutFileName1, "rb");
2133
2134 if (Fp == NULL) {
2135 Error (NULL, 0, 0001, "Error opening file", OutFileName1);
2136 if (StartAddressPtr) {
2137 free (StartAddressPtr);
2138 }
2139 return EFI_ABORTED;
2140 }
2141
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);
2145
2146 if (Fp) {
2147 fclose (Fp);
2148 }
2149
2150 if (StartAddressPtr) {
2151 free (StartAddressPtr);
2152 }
2153
2154 Status = EFI_SUCCESS;
2155 return Status;
2156 }
2157
2158 EFI_STATUS
2159 UpdateSymFile (
2160 IN UINT64 BaseAddress,
2161 IN CHAR8 *DestFileName,
2162 IN CHAR8 *SourceFileName,
2163 IN UINT64 FileSize
2164
2165 )
2166 /*++
2167
2168 Routine Description:
2169
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.
2172
2173 Arguments:
2174
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.
2179
2180 Returns:
2181
2182 EFI_SUCCESS - The function completed successfully.
2183 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2184 EFI_ABORTED - An error occurred.
2185
2186 --*/
2187 {
2188 FILE *SourceFile;
2189 FILE *DestFile;
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;
2197 long StartLocation;
2198
2199 //
2200 // Verify input parameters.
2201 //
2202 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
2203 return EFI_INVALID_PARAMETER;
2204 }
2205
2206 //
2207 // Open the source file
2208 //
2209 SourceFile = fopen (SourceFileName, "r");
2210 if (SourceFile == NULL) {
2211
2212 //
2213 // SYM files are not required.
2214 //
2215 return EFI_SUCCESS;
2216 }
2217
2218 //
2219 // Use the file name minus extension as the base for tokens
2220 //
2221 strcpy (BaseToken, SourceFileName);
2222 strtok (BaseToken, ". \t\n");
2223 strcat (BaseToken, "__");
2224
2225 //
2226 // Open the destination file
2227 //
2228 DestFile = fopen (DestFileName, "a+");
2229 if (DestFile == NULL) {
2230 fclose (SourceFile);
2231 Error (NULL, 0, 0001, "Error opening file", DestFileName);
2232 return EFI_ABORTED;
2233 }
2234
2235 //
2236 // If this is the beginning of the output file, write the symbol format info.
2237 //
2238 if (fseek (DestFile, 0, SEEK_END) != 0) {
2239 fclose (SourceFile);
2240 fclose (DestFile);
2241 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2242 return EFI_ABORTED;
2243 }
2244
2245 StartLocation = ftell (DestFile);
2246
2247 if (StartLocation == 0) {
2248 fprintf (DestFile, "TEXTSYM format | V1.0\n");
2249 } else if (StartLocation == -1) {
2250 fclose (SourceFile);
2251 fclose (DestFile);
2252 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");
2253 return EFI_ABORTED;
2254 }
2255
2256 //
2257 // Read the first line
2258 //
2259 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
2260 Buffer[0] = 0;
2261 }
2262
2263 //
2264 // Make sure it matches the expected sym format
2265 //
2266 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
2267 fclose (SourceFile);
2268 fclose (DestFile);
2269 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2270 return EFI_ABORTED;
2271 }
2272
2273 //
2274 // Read in the file
2275 //
2276 while (feof (SourceFile) == 0) {
2277
2278 //
2279 // Read a line
2280 //
2281 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {
2282
2283 //
2284 // Get the token address
2285 //
2286 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
2287 if (TokenAddress > FileSize) {
2288 //
2289 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2290 //
2291 break;
2292 }
2293
2294 //
2295 // Add the base address, the size of the FFS file header and the size of the peim header.
2296 //
2297 TokenAddress += BaseAddress &~IPF_CACHE_BIT;
2298
2299 fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress);
2300 fprintf (DestFile, "%s | %s\n %s\n", Section, Token, BaseToken);
2301 }
2302 }
2303
2304 fclose (SourceFile);
2305 fclose (DestFile);
2306 return EFI_SUCCESS;
2307 }
2308
2309 EFI_STATUS
2310 CalculateFitTableChecksum (
2311 VOID
2312 )
2313 /*++
2314
2315 Routine Description:
2316
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;.
2320
2321 Arguments:
2322
2323 NONE
2324
2325 Returns:
2326
2327 Status - Value returned by call to CalculateChecksum8 ()
2328 EFI_SUCCESS - The function completed successfully
2329
2330 --*/
2331 {
2332 FIT_TABLE *TmpFitPtr;
2333 UINT64 FitTableAdd;
2334 UINT64 FitTableAddOffset;
2335 UINTN RelativeAddress;
2336 UINTN Size;
2337
2338 //
2339 // Read the Fit Table address from Itanium-based address map.
2340 //
2341 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
2342
2343 //
2344 // Translate this Itanium-based address in terms of local buffer address which
2345 // contains the image for Boot Strapped File
2346 //
2347 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
2348 FitTableAdd = *(UINTN *) RelativeAddress;
2349
2350 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
2351
2352 TmpFitPtr = (FIT_TABLE *) RelativeAddress;
2353
2354 Size = TmpFitPtr->CompSize * 16;
2355
2356 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
2357 TmpFitPtr->CheckSum = 0;
2358 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);
2359 } else {
2360 TmpFitPtr->CheckSum = 0;
2361 }
2362
2363 return EFI_SUCCESS;
2364 }
2365
2366 VOID
2367 Version (
2368 VOID
2369 )
2370 /*++
2371
2372 Routine Description:
2373
2374 Displays the standard utility information to SDTOUT
2375
2376 Arguments:
2377
2378 None
2379
2380 Returns:
2381
2382 None
2383
2384 --*/
2385 {
2386 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
2387 }
2388
2389 VOID
2390 Usage (
2391 VOID
2392 )
2393 /*++
2394
2395 Routine Description:
2396
2397 Displays the utility usage syntax to STDOUT
2398
2399 Arguments:
2400
2401 None
2402
2403 Returns:
2404
2405 None
2406
2407 --*/
2408 {
2409 //
2410 // Summary usage
2411 //
2412 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);
2413
2414 //
2415 // Copyright declaration
2416 //
2417 fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
2418 //
2419 // Details Option
2420 //
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");
2436 }
2437
2438 int
2439 main (
2440 IN int argc,
2441 IN char **argv
2442 )
2443 /*++
2444
2445 Routine Description:
2446
2447 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2448 part of firmware volume image.
2449
2450 Arguments:
2451
2452 argc - The count of the parameters
2453 argv - The parameters
2454
2455
2456 Returns:
2457
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
2465
2466 --*/
2467 {
2468 UINT8 Index;
2469 UINT64 StartAddress1;
2470 UINT64 StartAddress2;
2471 UINT64 FwVolSize1;
2472 UINT64 FwVolSize2;
2473 BOOLEAN FirstRoundO;
2474 BOOLEAN FirstRoundB;
2475 BOOLEAN FirstRoundS;
2476 EFI_STATUS Status;
2477 FILE *VtfFP;
2478 CHAR8 *VtfFileName;
2479
2480 SetUtilityName (UTILITY_NAME);
2481
2482 //
2483 // Initialize variables
2484 //
2485 StartAddress1 = 0;
2486 StartAddress2 = 0;
2487 FwVolSize1 = 0;
2488 FwVolSize2 = 0;
2489 FirstRoundB = TRUE;
2490 FirstRoundS = TRUE;
2491 FirstRoundO = TRUE;
2492 DebugMode = FALSE;
2493 OutFileName1 = NULL;
2494 OutFileName2 = NULL;
2495 VtfFP = NULL;
2496 DebugLevel = 0;
2497
2498 //
2499 // Verify the correct number of arguments
2500 //
2501 if (argc == 1) {
2502 Usage();
2503 return 0;
2504 }
2505
2506 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
2507 Usage();
2508 return 0;
2509 }
2510
2511 if ((strcmp(argv[1], "--version") == 0)) {
2512 Version();
2513 return 0;
2514 }
2515
2516 //
2517 // Parse the command line arguments
2518 //
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");
2523 goto ERROR;
2524 }
2525 //
2526 // Get the output file name
2527 //
2528 VTF_OUTPUT = TRUE;
2529 if (FirstRoundO) {
2530 //
2531 // It's the first output file name
2532 //
2533 OutFileName1 = (CHAR8 *)argv[Index+1];
2534 FirstRoundO = FALSE;
2535 } else {
2536 //
2537 //It's the second output file name
2538 //
2539 OutFileName2 = (CHAR8 *)argv[Index+1];
2540 }
2541 continue;
2542 }
2543
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");
2547 goto ERROR;
2548 }
2549 //
2550 // Get the input VTF file name
2551 //
2552 VtfFileName = argv[Index+1];
2553 VtfFP = fopen(VtfFileName, "rb");
2554 if (VtfFP == NULL) {
2555 Error (NULL, 0, 0001, "Error opening file", VtfFileName);
2556 goto ERROR;
2557 }
2558 continue;
2559 }
2560
2561 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {
2562 if (FirstRoundB) {
2563 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
2564 FirstRoundB = FALSE;
2565 } else {
2566 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
2567 }
2568 if (Status != EFI_SUCCESS) {
2569 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);
2570 goto ERROR;
2571 }
2572 continue;
2573 }
2574
2575 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {
2576 if (FirstRoundS) {
2577 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
2578 FirstRoundS = FALSE;
2579 } else {
2580 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
2581 SecondVTF = TRUE;
2582 }
2583
2584 if (Status != EFI_SUCCESS) {
2585 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);
2586 goto ERROR;
2587 }
2588 continue;
2589 }
2590
2591 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
2592 VerboseMode = TRUE;
2593 Index--;
2594 continue;
2595 }
2596
2597 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
2598 QuietMode = TRUE;
2599 Index--;
2600 continue;
2601 }
2602
2603 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
2604 //
2605 // debug level specified
2606 //
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]);
2610 goto ERROR;
2611 }
2612 if (DebugLevel > 9) {
2613 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);
2614 goto ERROR;
2615 }
2616 if((DebugLevel <= 9) &&(DebugLevel >= 5)) {
2617 DebugMode = TRUE;
2618 } else {
2619 DebugMode = FALSE;
2620 }
2621 continue;
2622 }
2623
2624 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);
2625 goto ERROR;
2626 }
2627
2628 if (VtfFP == NULL) {
2629 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2630 goto ERROR;
2631 }
2632
2633 if (FirstRoundB) {
2634 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");
2635 goto ERROR;
2636 }
2637
2638 if (FirstRoundS) {
2639 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");
2640 goto ERROR;
2641 }
2642 //
2643 // All Parameters has been parsed, now set the message print level
2644 //
2645 if (QuietMode) {
2646 SetPrintLevel(40);
2647 } else if (VerboseMode) {
2648 SetPrintLevel(15);
2649 } else if (DebugMode) {
2650 SetPrintLevel(DebugLevel);
2651 }
2652
2653 if (VerboseMode) {
2654 VerboseMsg("%s tool start.\n", UTILITY_NAME);
2655 }
2656
2657 if (VTF_OUTPUT == FALSE) {
2658 if (SecondVTF == TRUE) {
2659 OutFileName1 = VTF_OUTPUT_FILE1;
2660 OutFileName2 = VTF_OUTPUT_FILE2;
2661 } else {
2662 OutFileName1 = VTF_OUTPUT_FILE1;
2663 }
2664 SymFileName = VTF_SYM_FILE;
2665 } else {
2666 INTN OutFileNameLen = strlen(OutFileName1);
2667 INTN Index;
2668
2669 for (Index = OutFileNameLen; Index > 0; --Index) {
2670 if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') {
2671 break;
2672 }
2673 }
2674 if (Index == 0) {
2675 SymFileName = VTF_SYM_FILE;
2676 } else {
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';
2682 }
2683 if (DebugMode) {
2684 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);
2685 }
2686 }
2687
2688 //
2689 // Call the GenVtfImage
2690 //
2691 if (DebugMode) {
2692 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);
2693 }
2694 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);
2695
2696 if (EFI_ERROR (Status)) {
2697 switch (Status) {
2698
2699 case EFI_INVALID_PARAMETER:
2700 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2701 break;
2702
2703 case EFI_ABORTED:
2704 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");
2705 break;
2706
2707 case EFI_OUT_OF_RESOURCES:
2708 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2709 break;
2710
2711 case EFI_VOLUME_CORRUPTED:
2712 Error (NULL, 0, 3000, "Invalid", "No base address was specified.");
2713 break;
2714
2715 default:
2716 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );
2717 break;
2718 }
2719 }
2720 ERROR:
2721 if (VtfFP != NULL) {
2722 fclose (VtfFP);
2723 }
2724
2725 if (DebugMode) {
2726 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);
2727 }
2728
2729 if (VerboseMode) {
2730 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
2731 }
2732 return GetUtilityStatus();
2733 }