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