]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenVtf/GenVtf.c
c37122c853fd8e5cb1c9ed5622e537f1b594b453
[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_SUCCESS - The function completed successfully
1049
1050 --*/
1051 {
1052 UINTN RelativeAddress;
1053 UINT64 SalEntryAdd;
1054 FILE *Fp;
1055 UINTN Offset;
1056
1057 CHAR8 Buff[FILE_NAME_SIZE];
1058 CHAR8 Buff1[10];
1059 CHAR8 Buff2[10];
1060 CHAR8 OffsetStr[30];
1061 CHAR8 Buff3[10];
1062 CHAR8 Buff4[10];
1063 CHAR8 Buff5[10];
1064 CHAR8 Token[50];
1065
1066 Fp = fopen (LongFilePath (VtfInfo->CompSymName), "rb");
1067
1068 if (Fp == NULL) {
1069 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName);
1070 return EFI_INVALID_PARAMETER;
1071 }
1072
1073 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
1074 fscanf (
1075 Fp,
1076 "%s %s %s %s %s %s %s",
1077 Buff1,
1078 Buff2,
1079 OffsetStr,
1080 Buff3,
1081 Buff4,
1082 Buff5,
1083 Token
1084 );
1085 if (strnicmp (Token, "SALE_ENTRY", 10) == 0) {
1086 break;
1087 }
1088 }
1089
1090 Offset = strtoul (OffsetStr, NULL, 16);
1091
1092 *CompStartAddress += Offset;
1093 SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
1094
1095 GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
1096
1097 memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
1098
1099 if (Fp != NULL) {
1100 fclose (Fp);
1101 }
1102
1103 return EFI_SUCCESS;
1104 }
1105
1106 EFI_STATUS
1107 CreateAndUpdateComponent (
1108 IN PARSED_VTF_INFO *VtfInfo
1109 )
1110 /*++
1111
1112 Routine Description:
1113
1114 This function reads the binary file for each components and update them
1115 in VTF Buffer as well as in FIT table. If the component is located in non
1116 VTF area, only the FIT table address will be updated
1117
1118 Arguments:
1119
1120 VtfInfo - Pointer to Parsed Info
1121
1122 Returns:
1123
1124 EFI_SUCCESS - The function completed successful
1125 EFI_ABORTED - Aborted due to one of the many reasons like:
1126 (a) Component Size greater than the specified size.
1127 (b) Error opening files.
1128 (c) Fail to get the FIT table address.
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 NumAdjustByte;
1139 UINT8 *Buffer;
1140 FILE *Fp;
1141 FIT_TABLE *CompFitPtr;
1142 BOOLEAN Aligncheck;
1143
1144 if (VtfInfo->LocationType == NONE) {
1145 UpdateFitEntryForNonVTFComp (VtfInfo);
1146 return EFI_SUCCESS;
1147 }
1148
1149 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");
1150
1151 if (Fp == NULL) {
1152 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
1153 return EFI_ABORTED;
1154 }
1155
1156 FileSize = _filelength (fileno (Fp));
1157 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1158
1159 //
1160 // BUGBUG: Satish to correct
1161 //
1162 FileSize -= SIZE_OF_PAL_HEADER;
1163 }
1164
1165 if (VtfInfo->PreferredSize) {
1166 if (FileSize > VtfInfo->CompSize) {
1167 fclose (Fp);
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 fclose (Fp);
1178 return EFI_OUT_OF_RESOURCES;
1179 }
1180 memset (Buffer, 0, (UINTN) FileSize);
1181
1182 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1183
1184 //
1185 // Read first 64 bytes of PAL header and use it to find version info
1186 //
1187 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1188
1189 //
1190 // PAL header contains the version info. Currently, we will use the header
1191 // to read version info and then discard.
1192 //
1193 if (!VtfInfo->VersionPresent) {
1194 GetComponentVersionInfo (VtfInfo, Buffer);
1195 }
1196 }
1197
1198 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1199 fclose (Fp);
1200
1201 //
1202 // If it is non PAL_B component, pass the entire buffer to get the version
1203 // info and implement any specific case inside GetComponentVersionInfo.
1204 //
1205 if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
1206 if (!VtfInfo->VersionPresent) {
1207 GetComponentVersionInfo (VtfInfo, Buffer);
1208 }
1209 }
1210
1211 if (VtfInfo->LocationType == SECOND_VTF) {
1212
1213 CompStartAddress = (Vtf2LastStartAddress - FileSize);
1214 } else {
1215 CompStartAddress = (Vtf1LastStartAddress - FileSize);
1216 }
1217
1218 if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
1219 Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
1220 } else {
1221 Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
1222 }
1223
1224 if (!Aligncheck) {
1225 CompStartAddress -= NumAdjustByte;
1226 }
1227
1228 if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) {
1229 Vtf2LastStartAddress = CompStartAddress;
1230 Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
1231 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
1232 } else if (VtfInfo->LocationType == FIRST_VTF) {
1233 Vtf1LastStartAddress = CompStartAddress;
1234 Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
1235 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
1236 } else {
1237 free (Buffer);
1238 Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
1239 return EFI_INVALID_PARAMETER;
1240 }
1241
1242 if (EFI_ERROR (Status)) {
1243 free (Buffer);
1244 return EFI_ABORTED;
1245 }
1246
1247 GetNextAvailableFitPtr (&CompFitPtr);
1248 if (CompFitPtr == NULL) {
1249 free (Buffer);
1250 return EFI_ABORTED;
1251 }
1252
1253 CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
1254 if ((FileSize % 16) != 0) {
1255 free (Buffer);
1256 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1257 return EFI_INVALID_PARAMETER;
1258 }
1259 //assert ((FileSize % 16) == 0);
1260 CompFitPtr->CompSize = (UINT32) (FileSize / 16);
1261 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
1262 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
1263 if (VtfInfo->CheckSumRequired) {
1264 CompFitPtr->CheckSum = 0;
1265 CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
1266 }
1267
1268 //
1269 // Free the buffer
1270 //
1271 if (Buffer) {
1272 free (Buffer);
1273 }
1274
1275 //
1276 // Update the SYM file for this component based on it's start address.
1277 //
1278 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
1279 if (EFI_ERROR (Status)) {
1280
1281 //
1282 // At this time, SYM files are not required, so continue on error.
1283 //
1284 }
1285
1286 // !!!!!!!!!!!!!!!!!!!!!
1287 // BUGBUG:
1288 // This part of the code is a temporary line since PEICORE is going to be inside
1289 // VTF till we work out how to determine the SALE_ENTRY through it. We will need
1290 // to clarify so many related questions
1291 // !!!!!!!!!!!!!!!!!!!!!!!
1292
1293 if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
1294 Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);
1295 }
1296
1297 return Status;
1298 }
1299
1300 EFI_STATUS
1301 CreateAndUpdatePAL_A (
1302 IN PARSED_VTF_INFO *VtfInfo
1303 )
1304 /*++
1305
1306 Routine Description:
1307
1308 This function reads the binary file for each components and update them
1309 in VTF Buffer as well as FIT table
1310
1311 Arguments:
1312
1313 VtfInfo - Pointer to Parsed Info
1314
1315 Returns:
1316
1317 EFI_ABORTED - Due to one of the following reasons:
1318 (a)Error Opening File
1319 (b)The PAL_A Size is more than specified size status
1320 One of the values mentioned below returned from
1321 call to UpdateSymFile
1322 EFI_SUCCESS - The function completed successfully.
1323 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
1324 EFI_ABORTED - An error occurred.UpdateSymFile
1325 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1326
1327 --*/
1328 {
1329 EFI_STATUS Status;
1330 UINT64 PalStartAddress;
1331 UINT64 AbsAddress;
1332 UINTN RelativeAddress;
1333 UINT64 FileSize;
1334 UINT8 *Buffer;
1335 FILE *Fp;
1336 FIT_TABLE *PalFitPtr;
1337
1338 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");
1339
1340 if (Fp == NULL) {
1341 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
1342 return EFI_ABORTED;
1343 }
1344
1345 FileSize = _filelength (fileno (Fp));
1346 if (FileSize < 64) {
1347 fclose (Fp);
1348 Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
1349 return EFI_INVALID_PARAMETER;
1350 }
1351 FileSize -= SIZE_OF_PAL_HEADER;
1352
1353
1354 if (VtfInfo->PreferredSize) {
1355 if (FileSize > VtfInfo->CompSize) {
1356 fclose (Fp);
1357 Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
1358 return EFI_ABORTED;
1359 }
1360
1361 FileSize = VtfInfo->CompSize;
1362 }
1363
1364 Buffer = malloc ((UINTN) FileSize);
1365 if (Buffer == NULL) {
1366 fclose (Fp);
1367 return EFI_OUT_OF_RESOURCES;
1368 }
1369 memset (Buffer, 0, (UINTN) FileSize);
1370
1371 //
1372 // Read, Get version Info and discard the PAL header.
1373 //
1374 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1375
1376 //
1377 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1378 //
1379 if (!VtfInfo->VersionPresent) {
1380 GetComponentVersionInfo (VtfInfo, Buffer);
1381 }
1382
1383 //
1384 // Read PAL_A file in a buffer
1385 //
1386 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1387 fclose (Fp);
1388
1389 PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);
1390 Vtf1LastStartAddress = PalStartAddress;
1391 Vtf1TotalSize += (UINT32) FileSize;
1392 Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
1393
1394 AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
1395 GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
1396 PalFitPtr = (FIT_TABLE *) RelativeAddress;
1397 PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;
1398 //assert ((FileSize % 16) == 0);
1399 if ((FileSize % 16) != 0) {
1400 free (Buffer);
1401 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
1402 return EFI_INVALID_PARAMETER;
1403 }
1404
1405 PalFitPtr->CompSize = (UINT32) (FileSize / 16);
1406 PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
1407 PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
1408 if (VtfInfo->CheckSumRequired) {
1409 PalFitPtr->CheckSum = 0;
1410 PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
1411 }
1412
1413 if (Buffer) {
1414 free (Buffer);
1415 }
1416
1417 //
1418 // Update the SYM file for this component based on it's start address.
1419 //
1420 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
1421 if (EFI_ERROR (Status)) {
1422
1423 //
1424 // At this time, SYM files are not required, so continue on error.
1425 //
1426 }
1427
1428 return Status;
1429 }
1430
1431 EFI_STATUS
1432 CreateFitTableAndInitialize (
1433 IN PARSED_VTF_INFO *VtfInfo
1434 )
1435 /*++
1436
1437 Routine Description:
1438
1439 This function creates and intializes FIT table which would be used to
1440 add component info inside this
1441
1442 Arguments:
1443
1444 VtfInfo - Pointer to Parsed Info
1445
1446 Returns:
1447
1448 EFI_ABORTED - Aborted due to no size information
1449 EFI_SUCCESS - The function completed successfully
1450
1451 --*/
1452 {
1453 UINT64 PalFitTableAdd;
1454 UINT64 FitTableAdd;
1455 UINT64 FitTableAddressOffset;
1456 FIT_TABLE *PalFitPtr;
1457 FIT_TABLE *FitStartPtr;
1458 UINTN NumFitComp;
1459 UINTN RelativeAddress;
1460 UINTN Index;
1461
1462 if (!VtfInfo->PreferredSize) {
1463 Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
1464 return EFI_ABORTED;
1465 }
1466
1467 if ((VtfInfo->CompSize % 16) != 0) {
1468 Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
1469 }
1470
1471 PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
1472 GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
1473 PalFitPtr = (FIT_TABLE *) RelativeAddress;
1474 PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize);
1475
1476 FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize;
1477 FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
1478 GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
1479 *(UINT64 *) RelativeAddress = FitTableAdd;
1480
1481 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
1482
1483 //
1484 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1485 //
1486 FitStartPtr = (FIT_TABLE *) RelativeAddress;
1487
1488 strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "
1489 assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
1490 FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16;
1491 FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
1492
1493 //
1494 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1495 // determine what to do for things like the FV component that aren't easily checksummed.
1496 // The checksum will be done once we are done with all the componet update in the FIT
1497 // table
1498 //
1499 FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
1500
1501 NumFitComp = FitStartPtr->CompSize;
1502
1503 FitStartPtr++;
1504
1505 //
1506 // Intialize remaining FIT table space to UNUSED fit component type
1507 // so that when we need to create a FIT entry for a component, we can
1508 // locate a free one and use it.
1509 //
1510 for (Index = 0; Index < (NumFitComp - 1); Index++) {
1511 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED
1512 FitStartPtr++;
1513 }
1514
1515 Vtf1TotalSize += VtfInfo->CompSize;
1516 Vtf1LastStartAddress -= VtfInfo->CompSize;
1517
1518 return EFI_SUCCESS;
1519 }
1520
1521 EFI_STATUS
1522 WriteVtfBinary (
1523 IN CHAR8 *FileName,
1524 IN UINT32 VtfSize,
1525 IN LOC_TYPE LocType
1526 )
1527 /*++
1528
1529 Routine Description:
1530
1531 Write Firmware Volume from memory to a file.
1532
1533 Arguments:
1534
1535 FileName - Output File Name which needed to be created/
1536 VtfSize - FileSize
1537 LocType - The type of the VTF
1538
1539 Returns:
1540
1541 EFI_ABORTED - Returned due to one of the following resons:
1542 (a) Error Opening File
1543 (b) Failing to copy buffers
1544 EFI_SUCCESS - The fuction completes successfully
1545
1546 --*/
1547 {
1548 FILE *Fp;
1549 UINTN NumByte;
1550 VOID *VtfBuffer;
1551 UINTN RelativeAddress;
1552
1553 if (LocType == FIRST_VTF) {
1554 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1555 VtfBuffer = (VOID *) RelativeAddress;
1556 } else {
1557 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1558 VtfBuffer = (VOID *) RelativeAddress;
1559 }
1560
1561 Fp = fopen (LongFilePath (FileName), "wb");
1562 if (Fp == NULL) {
1563 Error (NULL, 0, 0001, "Error opening file", FileName);
1564 return EFI_ABORTED;
1565 }
1566
1567 NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);
1568
1569 if (Fp) {
1570 fclose (Fp);
1571 }
1572
1573 if (NumByte != (sizeof (UINT8) * VtfSize)) {
1574 Error (NULL, 0, 0002, "Error writing file", FileName);
1575 return EFI_ABORTED;
1576 }
1577
1578 return EFI_SUCCESS;
1579 }
1580
1581 EFI_STATUS
1582 UpdateVtfBuffer (
1583 IN UINT64 StartAddress,
1584 IN UINT8 *Buffer,
1585 IN UINT64 DataSize,
1586 IN LOC_TYPE LocType
1587 )
1588 /*++
1589
1590 Routine Description:
1591
1592 Update the Firmware Volume Buffer with requested buffer data
1593
1594 Arguments:
1595
1596 StartAddress - StartAddress in buffer. This number will automatically
1597 point to right address in buffer where data needed
1598 to be updated.
1599 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1600 DataSize - Size of the data needed to be copied.
1601 LocType - The type of the VTF: First or Second
1602
1603 Returns:
1604
1605 EFI_ABORTED - The input parameter is error
1606 EFI_SUCCESS - The function completed successfully
1607
1608 --*/
1609 {
1610 UINT8 *LocalBufferPtrToWrite;
1611
1612 if (LocType == FIRST_VTF) {
1613 if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) {
1614 Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
1615 return EFI_ABORTED;
1616 }
1617
1618 LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;
1619
1620 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
1621
1622 } else {
1623
1624 if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {
1625 Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");
1626 return EFI_ABORTED;
1627 }
1628 LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;
1629 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
1630 }
1631
1632 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
1633
1634 return EFI_SUCCESS;
1635 }
1636
1637 EFI_STATUS
1638 UpdateFfsHeader (
1639 IN UINT32 TotalVtfSize,
1640 IN LOC_TYPE LocType
1641 )
1642 /*++
1643
1644 Routine Description:
1645
1646 Update the Firmware Volume Buffer with requested buffer data
1647
1648 Arguments:
1649
1650 TotalVtfSize - Size of the VTF
1651 Fileoffset - The start of the file relative to the start of the FV.
1652 LocType - The type of the VTF
1653
1654 Returns:
1655
1656 EFI_SUCCESS - The function completed successfully
1657 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1658
1659 --*/
1660 {
1661 EFI_FFS_FILE_HEADER *FileHeader;
1662 UINTN RelativeAddress;
1663 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1664
1665 //
1666 // Find the VTF file header location
1667 //
1668 if (LocType == FIRST_VTF) {
1669 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1670 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1671 } else {
1672 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1673 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1674 }
1675
1676 if (FileHeader == NULL) {
1677 return EFI_INVALID_PARAMETER;
1678 }
1679
1680 //
1681 // write header
1682 //
1683 memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
1684 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
1685 FileHeader->Type = EFI_FV_FILETYPE_RAW;
1686 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
1687
1688 //
1689 // Now FileSize includes the EFI_FFS_FILE_HEADER
1690 //
1691 FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);
1692 FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);
1693 FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);
1694
1695 //
1696 // Fill in checksums and state, all three must be zero for the checksums.
1697 //
1698 FileHeader->IntegrityCheck.Checksum.Header = 0;
1699 FileHeader->IntegrityCheck.Checksum.File = 0;
1700 FileHeader->State = 0;
1701 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
1702 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) (FileHeader + 1), TotalVtfSize - sizeof (EFI_FFS_FILE_HEADER));
1703 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
1704
1705 return EFI_SUCCESS;
1706 }
1707
1708 EFI_STATUS
1709 ValidateAddressAndSize (
1710 IN UINT64 BaseAddress,
1711 IN UINT64 FwVolSize
1712 )
1713 /*++
1714
1715 Routine Description:
1716
1717 Update the Firmware Volume Buffer with requested buffer data
1718
1719 Arguments:
1720
1721 BaseAddress - Base address for the Fw Volume.
1722
1723 FwVolSize - Total Size of the FwVolume to which VTF will be attached..
1724
1725 Returns:
1726
1727 EFI_SUCCESS - The function completed successfully
1728 EFI_UNSUPPORTED - The input parameter is error
1729
1730 --*/
1731 {
1732 if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
1733 return EFI_SUCCESS;
1734 }
1735
1736 return EFI_UNSUPPORTED;
1737 }
1738
1739 EFI_STATUS
1740 UpdateIA32ResetVector (
1741 IN CHAR8 *FileName,
1742 IN UINT64 FirstFwVSize
1743 )
1744 /*++
1745
1746 Routine Description:
1747
1748 Update the 16 byte IA32 Reset vector to maintain the compatibility
1749
1750 Arguments:
1751
1752 FileName - Binary file name which contains the IA32 Reset vector info..
1753 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
1754
1755 Returns:
1756
1757 EFI_SUCCESS - The function completed successfully
1758 EFI_ABORTED - Invalid File Size
1759 EFI_INVALID_PARAMETER - Bad File Name
1760 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1761
1762 --*/
1763 {
1764 UINT8 *Buffer;
1765 UINT8 *LocalVtfBuffer;
1766 UINTN FileSize;
1767 FILE *Fp;
1768
1769 if (!strcmp (FileName, "")) {
1770 return EFI_INVALID_PARAMETER;
1771 }
1772
1773 Fp = fopen (LongFilePath (FileName), "rb");
1774
1775 if (Fp == NULL) {
1776 Error (NULL, 0, 0001, "Error opening file", FileName);
1777 return EFI_ABORTED;
1778 }
1779
1780 FileSize = _filelength (fileno (Fp));
1781
1782 if (FileSize > 16) {
1783 fclose (Fp);
1784 return EFI_ABORTED;
1785 }
1786
1787 Buffer = malloc (FileSize);
1788 if (Buffer == NULL) {
1789 fclose (Fp);
1790 return EFI_OUT_OF_RESOURCES;
1791 }
1792
1793 fread (Buffer, sizeof (UINT8), FileSize, Fp);
1794
1795 LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;
1796 memcpy (LocalVtfBuffer, Buffer, FileSize);
1797
1798 if (Buffer) {
1799 free (Buffer);
1800 }
1801
1802 if (Fp != NULL) {
1803 fclose (Fp);
1804 }
1805 return EFI_SUCCESS;
1806 }
1807
1808 VOID
1809 CleanUpMemory (
1810 VOID
1811 )
1812 /*++
1813
1814 Routine Description:
1815
1816 This function cleans up any allocated buffer
1817
1818 Arguments:
1819
1820 NONE
1821
1822 Returns:
1823
1824 NONE
1825
1826 --*/
1827 {
1828 PARSED_VTF_INFO *TempFileListPtr;
1829
1830 if (Vtf1Buffer) {
1831 free (Vtf1Buffer);
1832 }
1833
1834 if (Vtf2Buffer) {
1835 free (Vtf2Buffer);
1836 }
1837
1838 //
1839 // Cleanup the buffer which was allocated to read the file names from FV.INF
1840 //
1841 FileListPtr = FileListHeadPtr;
1842 while (FileListPtr != NULL) {
1843 TempFileListPtr = FileListPtr->NextVtfInfo;
1844 free (FileListPtr);
1845 FileListPtr = TempFileListPtr;
1846 }
1847 }
1848
1849 EFI_STATUS
1850 ProcessAndCreateVtf (
1851 IN UINT64 Size
1852 )
1853 /*++
1854
1855 Routine Description:
1856
1857 This function process the link list created during INF file parsing
1858 and create component in VTF and updates its info in FIT table
1859
1860 Arguments:
1861
1862 Size - Size of the Firmware Volume of which, this VTF belongs to.
1863
1864 Returns:
1865
1866 EFI_UNSUPPORTED - Unknown FIT type
1867 EFI_SUCCESS - The function completed successfully
1868
1869 --*/
1870 {
1871 EFI_STATUS Status;
1872 PARSED_VTF_INFO *ParsedInfoPtr;
1873
1874 Status = EFI_SUCCESS;
1875
1876 ParsedInfoPtr = FileListHeadPtr;
1877
1878 while (ParsedInfoPtr != NULL) {
1879
1880 switch (ParsedInfoPtr->CompType) {
1881 //
1882 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1883 //
1884 case COMP_TYPE_FIT_HEADER:
1885 //COMP_TYPE_FIT_HEADER 0x00
1886 Status = CreateFitTableAndInitialize (ParsedInfoPtr);
1887 break;
1888
1889 //
1890 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1891 //
1892 case COMP_TYPE_FIT_PAL_A:
1893 //COMP_TYPE_FIT_PAL_A 0x0F
1894 Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
1895
1896 //
1897 // Based on VTF specification, once the PAL_A component has been written,
1898 // update the Firmware Volume info as FIT table. This will be utilized
1899 // to extract the Firmware Volume Start address where this VTF will be
1900 // of part.
1901 //
1902 if (Status == EFI_SUCCESS) {
1903 UpdateFitEntryForFwVolume (Size);
1904 }
1905 break;
1906
1907 case COMP_TYPE_FIT_FV_BOOT:
1908 //COMP_TYPE_FIT_FV_BOOT 0x7E
1909 //
1910 // Since FIT entry for Firmware Volume has been created and it is
1911 // located at (PAL_A start - 16 byte). So we will not process any
1912 // Firmware Volume related entry from INF file
1913 //
1914 Status = EFI_SUCCESS;
1915 break;
1916
1917 default:
1918 //
1919 // Any other component type should be handled here. This will create the
1920 // image in specified VTF and create appropriate entry about this
1921 // component in FIT Entry.
1922 //
1923 Status = CreateAndUpdateComponent (ParsedInfoPtr);
1924 if (EFI_ERROR (Status)) {
1925 Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);
1926 return EFI_ABORTED;
1927 } else {
1928 break;}
1929 }
1930
1931 ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;
1932 }
1933 return Status;
1934 }
1935
1936 EFI_STATUS
1937 GenerateVtfImage (
1938 IN UINT64 StartAddress1,
1939 IN UINT64 Size1,
1940 IN UINT64 StartAddress2,
1941 IN UINT64 Size2,
1942 IN FILE *fp
1943 )
1944 /*++
1945
1946 Routine Description:
1947
1948 This is the main function which will be called from application.
1949
1950 Arguments:
1951
1952 StartAddress1 - The start address of the first VTF
1953 Size1 - The size of the first VTF
1954 StartAddress2 - The start address of the second VTF
1955 Size2 - The size of the second VTF
1956 fp - The pointer to BSF inf file
1957
1958 Returns:
1959
1960 EFI_OUT_OF_RESOURCES - Can not allocate memory
1961 The return value can be any of the values
1962 returned by the calls to following functions:
1963 GetVtfRelatedInfoFromInfFile
1964 ProcessAndCreateVtf
1965 UpdateIA32ResetVector
1966 UpdateFfsHeader
1967 WriteVtfBinary
1968
1969 --*/
1970 {
1971 EFI_STATUS Status;
1972 FILE *VtfFP;
1973
1974 Status = EFI_UNSUPPORTED;
1975 VtfFP = fp;
1976
1977 if (StartAddress2 == 0) {
1978 SecondVTF = FALSE;
1979 } else {
1980 SecondVTF = TRUE;
1981 }
1982
1983 Fv1BaseAddress = StartAddress1;
1984 Fv1EndAddress = Fv1BaseAddress + Size1;
1985 if (Fv1EndAddress != 0x100000000ULL || Size1 < 0x100000) {
1986 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
1987 if (Size1 < 0x100000) {
1988 Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
1989 } else if (SecondVTF != TRUE) {
1990 Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
1991 }
1992 Usage();
1993 return EFI_INVALID_PARAMETER;
1994 }
1995
1996 //
1997 // The image buffer for the First VTF
1998 //
1999 Vtf1Buffer = malloc ((UINTN) Size1);
2000 if (Vtf1Buffer == NULL) {
2001 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2002 return EFI_OUT_OF_RESOURCES;
2003 }
2004 memset (Vtf1Buffer, 0x00, (UINTN) Size1);
2005 Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1;
2006 Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
2007
2008 if (SecondVTF) {
2009 Fv2BaseAddress = StartAddress2;
2010 Fv2EndAddress = Fv2BaseAddress + Size2;
2011 if (Fv2EndAddress != StartAddress1) {
2012 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
2013 if (SecondVTF == TRUE) {
2014 Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
2015 Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
2016 }
2017 Usage();
2018 return EFI_INVALID_PARAMETER;
2019 }
2020
2021 //
2022 // The image buffer for the second VTF
2023 //
2024 Vtf2Buffer = malloc ((UINTN) Size2);
2025 if (Vtf2Buffer == NULL) {
2026 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
2027 return EFI_OUT_OF_RESOURCES;
2028 }
2029 memset (Vtf2Buffer, 0x00, (UINTN) Size2);
2030 Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2;
2031 Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
2032 }
2033
2034 Status = GetVtfRelatedInfoFromInfFile (VtfFP);
2035
2036 if (Status != EFI_SUCCESS) {
2037 Error (NULL, 0, 0003, "Error parsing file", "the input file.");
2038 CleanUpMemory ();
2039 return Status;
2040 }
2041
2042 Status = ProcessAndCreateVtf (Size1);
2043 if (Status != EFI_SUCCESS) {
2044 CleanUpMemory ();
2045 return Status;
2046 }
2047
2048 if (SectionOptionFlag) {
2049 Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);
2050 if (Status != EFI_SUCCESS) {
2051 CleanUpMemory ();
2052 return Status;
2053 }
2054 }
2055
2056 //
2057 // Re arrange the FIT Table for Ascending order of their FIT Type..
2058 //
2059 SortFitTable ();
2060
2061 //
2062 // All components have been updated in FIT table. Now perform the FIT table
2063 // checksum. The following function will check if Checksum is required,
2064 // if yes, then it will perform the checksum otherwise not.
2065 //
2066 CalculateFitTableChecksum ();
2067
2068 //
2069 // Write the FFS header
2070 //
2071 Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
2072 Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
2073
2074 Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);
2075 if (Status != EFI_SUCCESS) {
2076 CleanUpMemory ();
2077 return Status;
2078 }
2079 //
2080 // Update the VTF buffer into specified VTF binary file
2081 //
2082 Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);
2083
2084 if (SecondVTF) {
2085 Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
2086 Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
2087 Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF);
2088 if (Status != EFI_SUCCESS) {
2089 CleanUpMemory ();
2090 return Status;
2091 }
2092
2093 //
2094 // Update the VTF buffer into specified VTF binary file
2095 //
2096 Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);
2097 }
2098
2099 CleanUpMemory ();
2100
2101 return Status;
2102 }
2103
2104 EFI_STATUS
2105 PeimFixupInFitTable (
2106 IN UINT64 StartAddress
2107 )
2108 /*++
2109
2110 Routine Description:
2111
2112 This function is an entry point to fixup SAL-E entry point.
2113
2114 Arguments:
2115
2116 StartAddress - StartAddress for PEIM.....
2117
2118 Returns:
2119
2120 EFI_SUCCESS - The function completed successfully
2121 EFI_ABORTED - Error Opening File
2122 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2123
2124 --*/
2125 {
2126 EFI_STATUS Status;
2127 FILE *Fp;
2128 UINT64 *StartAddressPtr;
2129 UINTN FirstFwVSize;
2130
2131 StartAddressPtr = malloc (sizeof (UINT64));
2132 if (StartAddressPtr == NULL) {
2133 return EFI_OUT_OF_RESOURCES;
2134 }
2135 *StartAddressPtr = StartAddress;
2136
2137 Fp = fopen (LongFilePath (OutFileName1), "rb");
2138
2139 if (Fp == NULL) {
2140 Error (NULL, 0, 0001, "Error opening file", OutFileName1);
2141 if (StartAddressPtr) {
2142 free (StartAddressPtr);
2143 }
2144 return EFI_ABORTED;
2145 }
2146
2147 FirstFwVSize = _filelength (fileno (Fp));
2148 fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);
2149 fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);
2150
2151 if (Fp) {
2152 fclose (Fp);
2153 }
2154
2155 if (StartAddressPtr) {
2156 free (StartAddressPtr);
2157 }
2158
2159 Status = EFI_SUCCESS;
2160 return Status;
2161 }
2162
2163 EFI_STATUS
2164 UpdateSymFile (
2165 IN UINT64 BaseAddress,
2166 IN CHAR8 *DestFileName,
2167 IN CHAR8 *SourceFileName,
2168 IN UINT64 FileSize
2169
2170 )
2171 /*++
2172
2173 Routine Description:
2174
2175 This function adds the SYM tokens in the source file to the destination file.
2176 The SYM tokens are updated to reflect the base address.
2177
2178 Arguments:
2179
2180 BaseAddress - The base address for the new SYM tokens.
2181 DestFileName - The destination file.
2182 SourceFileName - The source file.
2183 FileSize - Size of bin file.
2184
2185 Returns:
2186
2187 EFI_SUCCESS - The function completed successfully.
2188 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2189 EFI_ABORTED - An error occurred.
2190
2191 --*/
2192 {
2193 FILE *SourceFile;
2194 FILE *DestFile;
2195 CHAR8 Buffer[MAX_LONG_FILE_PATH];
2196 CHAR8 Type[MAX_LONG_FILE_PATH];
2197 CHAR8 Address[MAX_LONG_FILE_PATH];
2198 CHAR8 Section[MAX_LONG_FILE_PATH];
2199 CHAR8 Token[MAX_LONG_FILE_PATH];
2200 CHAR8 BaseToken[MAX_LONG_FILE_PATH];
2201 UINT64 TokenAddress;
2202 long StartLocation;
2203
2204 //
2205 // Verify input parameters.
2206 //
2207 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
2208 return EFI_INVALID_PARAMETER;
2209 }
2210
2211 //
2212 // Open the source file
2213 //
2214 SourceFile = fopen (LongFilePath (SourceFileName), "r");
2215 if (SourceFile == NULL) {
2216
2217 //
2218 // SYM files are not required.
2219 //
2220 return EFI_SUCCESS;
2221 }
2222
2223 //
2224 // Use the file name minus extension as the base for tokens
2225 //
2226 strcpy (BaseToken, SourceFileName);
2227 strtok (BaseToken, ". \t\n");
2228 strcat (BaseToken, "__");
2229
2230 //
2231 // Open the destination file
2232 //
2233 DestFile = fopen (LongFilePath (DestFileName), "a+");
2234 if (DestFile == NULL) {
2235 fclose (SourceFile);
2236 Error (NULL, 0, 0001, "Error opening file", DestFileName);
2237 return EFI_ABORTED;
2238 }
2239
2240 //
2241 // If this is the beginning of the output file, write the symbol format info.
2242 //
2243 if (fseek (DestFile, 0, SEEK_END) != 0) {
2244 fclose (SourceFile);
2245 fclose (DestFile);
2246 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
2247 return EFI_ABORTED;
2248 }
2249
2250 StartLocation = ftell (DestFile);
2251
2252 if (StartLocation == 0) {
2253 fprintf (DestFile, "TEXTSYM format | V1.0\n");
2254 } else if (StartLocation == -1) {
2255 fclose (SourceFile);
2256 fclose (DestFile);
2257 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");
2258 return EFI_ABORTED;
2259 }
2260
2261 //
2262 // Read the first line
2263 //
2264 if (fgets (Buffer, MAX_LONG_FILE_PATH, SourceFile) == NULL) {
2265 Buffer[0] = 0;
2266 }
2267
2268 //
2269 // Make sure it matches the expected sym format
2270 //
2271 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
2272 fclose (SourceFile);
2273 fclose (DestFile);
2274 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
2275 return EFI_ABORTED;
2276 }
2277
2278 //
2279 // Read in the file
2280 //
2281 while (feof (SourceFile) == 0) {
2282
2283 //
2284 // Read a line
2285 //
2286 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {
2287
2288 //
2289 // Get the token address
2290 //
2291 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
2292 if (TokenAddress > FileSize) {
2293 //
2294 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
2295 //
2296 break;
2297 }
2298
2299 //
2300 // Add the base address, the size of the FFS file header and the size of the peim header.
2301 //
2302 TokenAddress += BaseAddress &~IPF_CACHE_BIT;
2303
2304 fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress);
2305 fprintf (DestFile, "%s | %s\n %s\n", Section, Token, BaseToken);
2306 }
2307 }
2308
2309 fclose (SourceFile);
2310 fclose (DestFile);
2311 return EFI_SUCCESS;
2312 }
2313
2314 EFI_STATUS
2315 CalculateFitTableChecksum (
2316 VOID
2317 )
2318 /*++
2319
2320 Routine Description:
2321
2322 This function will perform byte checksum on the FIT table, if the the checksum required
2323 field is set to CheckSum required. If the checksum is not required then checksum byte
2324 will have value as 0;.
2325
2326 Arguments:
2327
2328 NONE
2329
2330 Returns:
2331
2332 Status - Value returned by call to CalculateChecksum8 ()
2333 EFI_SUCCESS - The function completed successfully
2334
2335 --*/
2336 {
2337 FIT_TABLE *TmpFitPtr;
2338 UINT64 FitTableAdd;
2339 UINT64 FitTableAddOffset;
2340 UINTN RelativeAddress;
2341 UINTN Size;
2342
2343 //
2344 // Read the Fit Table address from Itanium-based address map.
2345 //
2346 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
2347
2348 //
2349 // Translate this Itanium-based address in terms of local buffer address which
2350 // contains the image for Boot Strapped File
2351 //
2352 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
2353 FitTableAdd = *(UINTN *) RelativeAddress;
2354
2355 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
2356
2357 TmpFitPtr = (FIT_TABLE *) RelativeAddress;
2358
2359 Size = TmpFitPtr->CompSize * 16;
2360
2361 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
2362 TmpFitPtr->CheckSum = 0;
2363 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);
2364 } else {
2365 TmpFitPtr->CheckSum = 0;
2366 }
2367
2368 return EFI_SUCCESS;
2369 }
2370
2371 VOID
2372 Version (
2373 VOID
2374 )
2375 /*++
2376
2377 Routine Description:
2378
2379 Displays the standard utility information to SDTOUT
2380
2381 Arguments:
2382
2383 None
2384
2385 Returns:
2386
2387 None
2388
2389 --*/
2390 {
2391 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
2392 }
2393
2394 VOID
2395 Usage (
2396 VOID
2397 )
2398 /*++
2399
2400 Routine Description:
2401
2402 Displays the utility usage syntax to STDOUT
2403
2404 Arguments:
2405
2406 None
2407
2408 Returns:
2409
2410 None
2411
2412 --*/
2413 {
2414 //
2415 // Summary usage
2416 //
2417 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);
2418
2419 //
2420 // Copyright declaration
2421 //
2422 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
2423 //
2424 // Details Option
2425 //
2426 fprintf (stdout, "Options:\n");
2427 fprintf (stdout, " -f Input_file, --filename Input_file\n\
2428 Input_file is name of the BS Image INF file\n");
2429 fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\
2430 BaseAddress is the starting address of Firmware Volume\n\
2431 where Boot Strapped Image will reside.\n");
2432 fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\
2433 FwVolumeSize is the size of Firmware Volume.\n");
2434 fprintf (stdout, " -o FileName, --output FileName\n\
2435 File will be created to store the ouput content.\n");
2436 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
2437 fprintf (stdout, " --version Show program's version number and exit.\n");
2438 fprintf (stdout, " -h, --help Show this help message and exit.\n");
2439 fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
2440 fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
2441 }
2442
2443 int
2444 main (
2445 IN int argc,
2446 IN char **argv
2447 )
2448 /*++
2449
2450 Routine Description:
2451
2452 This utility uses GenVtf.dll to build a Boot Strap File Image which will be
2453 part of firmware volume image.
2454
2455 Arguments:
2456
2457 argc - The count of the parameters
2458 argv - The parameters
2459
2460
2461 Returns:
2462
2463 0 - No error conditions detected.
2464 1 - One or more of the input parameters is invalid.
2465 2 - A resource required by the utility was unavailable.
2466 - Most commonly this will be memory allocation or file creation.
2467 3 - GenFvImage.dll could not be loaded.
2468 4 - Error executing the GenFvImage dll.
2469 5 - Now this tool does not support the IA32 platform
2470
2471 --*/
2472 {
2473 UINT8 Index;
2474 UINT64 StartAddress1;
2475 UINT64 StartAddress2;
2476 UINT64 FwVolSize1;
2477 UINT64 FwVolSize2;
2478 BOOLEAN FirstRoundO;
2479 BOOLEAN FirstRoundB;
2480 BOOLEAN FirstRoundS;
2481 EFI_STATUS Status;
2482 FILE *VtfFP;
2483 CHAR8 *VtfFileName;
2484
2485 SetUtilityName (UTILITY_NAME);
2486
2487 //
2488 // Initialize variables
2489 //
2490 StartAddress1 = 0;
2491 StartAddress2 = 0;
2492 FwVolSize1 = 0;
2493 FwVolSize2 = 0;
2494 FirstRoundB = TRUE;
2495 FirstRoundS = TRUE;
2496 FirstRoundO = TRUE;
2497 DebugMode = FALSE;
2498 OutFileName1 = NULL;
2499 OutFileName2 = NULL;
2500 VtfFP = NULL;
2501 DebugLevel = 0;
2502
2503 //
2504 // Verify the correct number of arguments
2505 //
2506 if (argc == 1) {
2507 Usage();
2508 return 0;
2509 }
2510
2511 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
2512 Usage();
2513 return 0;
2514 }
2515
2516 if ((strcmp(argv[1], "--version") == 0)) {
2517 Version();
2518 return 0;
2519 }
2520
2521 //
2522 // Parse the command line arguments
2523 //
2524 for (Index = 1; Index < argc; Index += 2) {
2525 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {
2526 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
2527 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
2528 goto ERROR;
2529 }
2530 //
2531 // Get the output file name
2532 //
2533 VTF_OUTPUT = TRUE;
2534 if (FirstRoundO) {
2535 //
2536 // It's the first output file name
2537 //
2538 OutFileName1 = (CHAR8 *)argv[Index+1];
2539 FirstRoundO = FALSE;
2540 } else {
2541 //
2542 //It's the second output file name
2543 //
2544 OutFileName2 = (CHAR8 *)argv[Index+1];
2545 }
2546 continue;
2547 }
2548
2549 if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {
2550 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
2551 Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
2552 goto ERROR;
2553 }
2554 //
2555 // Get the input VTF file name
2556 //
2557 VtfFileName = argv[Index+1];
2558 if (VtfFP != NULL) {
2559 //
2560 // VTF file name has been given previously, override with the new value
2561 //
2562 fclose (VtfFP);
2563 }
2564 VtfFP = fopen (LongFilePath (VtfFileName), "rb");
2565 if (VtfFP == NULL) {
2566 Error (NULL, 0, 0001, "Error opening file", VtfFileName);
2567 goto ERROR;
2568 }
2569 continue;
2570 }
2571
2572 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {
2573 if (FirstRoundB) {
2574 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
2575 FirstRoundB = FALSE;
2576 } else {
2577 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
2578 }
2579 if (Status != EFI_SUCCESS) {
2580 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);
2581 goto ERROR;
2582 }
2583 continue;
2584 }
2585
2586 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {
2587 if (FirstRoundS) {
2588 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
2589 FirstRoundS = FALSE;
2590 } else {
2591 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
2592 SecondVTF = TRUE;
2593 }
2594
2595 if (Status != EFI_SUCCESS) {
2596 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);
2597 goto ERROR;
2598 }
2599 continue;
2600 }
2601
2602 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
2603 VerboseMode = TRUE;
2604 Index--;
2605 continue;
2606 }
2607
2608 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
2609 QuietMode = TRUE;
2610 Index--;
2611 continue;
2612 }
2613
2614 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
2615 //
2616 // debug level specified
2617 //
2618 Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);
2619 if (EFI_ERROR (Status)) {
2620 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);
2621 goto ERROR;
2622 }
2623 if (DebugLevel > 9) {
2624 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);
2625 goto ERROR;
2626 }
2627 if((DebugLevel <= 9) &&(DebugLevel >= 5)) {
2628 DebugMode = TRUE;
2629 } else {
2630 DebugMode = FALSE;
2631 }
2632 continue;
2633 }
2634
2635 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);
2636 goto ERROR;
2637 }
2638
2639 if (VtfFP == NULL) {
2640 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
2641 goto ERROR;
2642 }
2643
2644 if (FirstRoundB) {
2645 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");
2646 goto ERROR;
2647 }
2648
2649 if (FirstRoundS) {
2650 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");
2651 goto ERROR;
2652 }
2653 //
2654 // All Parameters has been parsed, now set the message print level
2655 //
2656 if (QuietMode) {
2657 SetPrintLevel(40);
2658 } else if (VerboseMode) {
2659 SetPrintLevel(15);
2660 } else if (DebugMode) {
2661 SetPrintLevel(DebugLevel);
2662 }
2663
2664 if (VerboseMode) {
2665 VerboseMsg("%s tool start.\n", UTILITY_NAME);
2666 }
2667
2668 if (VTF_OUTPUT == FALSE) {
2669 if (SecondVTF == TRUE) {
2670 OutFileName1 = VTF_OUTPUT_FILE1;
2671 OutFileName2 = VTF_OUTPUT_FILE2;
2672 } else {
2673 OutFileName1 = VTF_OUTPUT_FILE1;
2674 }
2675 SymFileName = VTF_SYM_FILE;
2676 } else {
2677 assert (OutFileName1);
2678 INTN OutFileNameLen = strlen(OutFileName1);
2679 INTN NewIndex;
2680
2681 for (NewIndex = OutFileNameLen; NewIndex > 0; --NewIndex) {
2682 if (OutFileName1[NewIndex] == '/' || OutFileName1[NewIndex] == '\\') {
2683 break;
2684 }
2685 }
2686 if (NewIndex == 0) {
2687 SymFileName = VTF_SYM_FILE;
2688 } else {
2689 INTN SymFileNameLen = NewIndex + 1 + strlen(VTF_SYM_FILE);
2690 SymFileName = malloc(SymFileNameLen + 1);
2691 if (SymFileName == NULL) {
2692 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
2693 goto ERROR;
2694 }
2695 memcpy(SymFileName, OutFileName1, NewIndex + 1);
2696 memcpy(SymFileName + NewIndex + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));
2697 SymFileName[SymFileNameLen] = '\0';
2698 }
2699 if (DebugMode) {
2700 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);
2701 }
2702 }
2703
2704 //
2705 // Call the GenVtfImage
2706 //
2707 if (DebugMode) {
2708 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);
2709 }
2710 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);
2711
2712 if (EFI_ERROR (Status)) {
2713 switch (Status) {
2714
2715 case EFI_INVALID_PARAMETER:
2716 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
2717 break;
2718
2719 case EFI_ABORTED:
2720 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");
2721 break;
2722
2723 case EFI_OUT_OF_RESOURCES:
2724 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
2725 break;
2726
2727 case EFI_VOLUME_CORRUPTED:
2728 Error (NULL, 0, 3000, "Invalid", "No base address was specified.");
2729 break;
2730
2731 default:
2732 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );
2733 break;
2734 }
2735 }
2736 ERROR:
2737 if (VtfFP != NULL) {
2738 fclose (VtfFP);
2739 }
2740
2741 if (DebugMode) {
2742 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);
2743 }
2744
2745 if (VerboseMode) {
2746 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
2747 }
2748 return GetUtilityStatus();
2749 }