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