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