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