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