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