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