]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/GenBsfImage/GenBsfImage.c
remove unnecessary check for NULL pointer.
[mirror_edk2.git] / Tools / CCode / Source / GenBsfImage / GenBsfImage.c
1 /*++
2
3 Copyright (c) 1999 - 2006, Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
11
12
13 Module Name:
14
15 GenBsfImage.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 // Module Coded to EFI 2.0 Coding Conventions
26 //
27 #include <FvLib.h>
28 #include <Common/UefiBaseTypes.h>
29 #include "GenBsfImage.h"
30 #include <Guid/FirmwareFileSystem.h>
31 #include "CommonLib.h"
32
33 //
34 // Global variables
35 //
36 EFI_GUID Bsf1NameGuid = EFI_IPF_VTF1_GUID
37 EFI_GUID Bsf2NameGuid = EFI_IPF_VTF2_GUID
38
39 CHAR8 **TokenStr;
40 CHAR8 **OrgStrTokPtr;
41
42 PARSED_BSF_INFO *FileListPtr;
43 PARSED_BSF_INFO *FileListHeadPtr;
44
45 VOID *Bsf1Buffer;
46 VOID *Bsf1EndBuffer;
47 VOID *Bsf2Buffer;
48 VOID *Bsf2EndBuffer;
49
50 UINTN ValidLineNum = 0;
51 UINTN ValidFFDFileListNum = 0;
52
53 //
54 // Section Description and their number of occurences in *.INF file
55 //
56 UINTN NumFvFiles = 0;
57 UINTN SectionOptionNum = 0;
58
59 //
60 // Global flag which will check for BSF Present, if yes then will be used
61 // to decide about adding FFS header to pad data
62 //
63 BOOLEAN BSFPresent = FALSE;
64
65 //
66 // Address related information
67 //
68 UINT64 Fv1BaseAddress = 0;
69 UINT64 Fv2BaseAddress = 0;
70 UINT64 Fv1EndAddress = 0;
71 UINT64 Fv2EndAddress = 0;
72 UINT32 Bsf1TotalSize = SIZE_TO_OFFSET_PAL_A_END;
73 UINT64 Bsf1LastStartAddress = 0;
74 UINT32 Bsf2TotalSize = 0;
75 UINT64 Bsf2LastStartAddress = 0;
76
77 UINT32 BufferToTop = 0;
78
79 //
80 // IA32 Reset Vector Bin name
81 //
82 CHAR8 IA32BinFile[FILE_NAME_SIZE];
83
84 //
85 // Function Implementations
86 //
87 VOID
88 BuildTokenList (
89 IN CHAR8 *Token
90 )
91 /*++
92 Routine Description:
93
94 This function builds the token list in an array which will be parsed later
95
96 Arguments:
97
98 Token - The pointer of string
99
100 Returns:
101
102 None
103
104 --*/
105 {
106 strcpy (*TokenStr, Token);
107 TokenStr++;
108 }
109
110 EFI_STATUS
111 ConvertVersionInfo (
112 IN CHAR8 *Str,
113 IN OUT UINT8 *MajorVer,
114 IN OUT UINT8 *MinorVer
115 )
116 /*++
117 Routine Description:
118
119 This function converts GUID string to GUID
120
121 Arguments:
122
123 Str - String representing in form XX.XX
124 MajorVer - The major vertion
125 MinorVer - The minor vertion
126
127 Returns:
128
129 EFI_SUCCESS - The fuction completed successfully.
130
131 --*/
132 {
133 CHAR8 StrPtr[40];
134 CHAR8 *Token;
135 UINTN Length;
136 UINTN Major;
137 UINTN Minor;
138
139 Major = 0;
140 Minor = 0;
141 memset (StrPtr, 0, 40);
142 Token = strtok (Str, ".");
143
144 while (Token != NULL) {
145 strcat (StrPtr, Token);
146 Token = strtok (NULL, ".");
147 }
148
149 Length = strlen (StrPtr);
150 sscanf (
151 StrPtr,
152 "%01x%02x",
153 &Major,
154 &Minor
155 );
156
157 *MajorVer = (UINT8) Major;
158 *MinorVer = (UINT8) Minor;
159 return EFI_SUCCESS;
160 }
161
162 VOID
163 TrimLine (
164 IN CHAR8 *Line
165 )
166 /*++
167 Routine Description:
168
169 This function cleans up the line by removing all whitespace and
170 comments
171
172 Arguments:
173
174 Line - The pointer of the string
175
176 Returns:
177
178 None
179
180 --*/
181 {
182 CHAR8 TmpLine[FILE_NAME_SIZE];
183 CHAR8 Char;
184 CHAR8 *Ptr0;
185 UINTN Index;
186 UINTN Index2;
187
188 //
189 // Change '#' to '//' for Comment style
190 //
191 if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {
192 Line[Ptr0 - Line] = 0;
193 }
194
195 //
196 // Initialize counters
197 //
198 Index = 0;
199 Index2 = 0;
200
201 while ((Char = Line[Index]) != 0) {
202 if ((Char != ' ') && (Char != '\t') && (Char != '\n')) {
203 TmpLine[Index2++] = Char;
204 }
205 Index++;
206 }
207
208 TmpLine[Index2] = 0;
209 strcpy (Line, TmpLine);
210 }
211
212 VOID
213 ValidLineCount (
214 IN FILE *Fp
215 )
216 /*++
217
218 Routine Description:
219
220 This function calculated number of valid lines in a input file.
221
222 Arguments:
223
224 Fp - Pointer to a file handle which has been opened.
225
226 Returns:
227
228 None
229
230 --*/
231 {
232 CHAR8 Buff[FILE_NAME_SIZE];
233
234 while (fgets (Buff, sizeof (Buff), Fp)) {
235 TrimLine (Buff);
236 if (Buff[0] == 0) {
237 continue;
238 }
239
240 ValidLineNum++;
241 }
242 }
243
244 VOID
245 ParseInputFile (
246 IN FILE *Fp
247 )
248 /*++
249
250 Routine Description:
251
252 This function parses the input file and tokenize the string
253
254 Arguments:
255
256 Fp - Pointer to a file handle which has been opened.
257
258 Returns:
259
260 None
261
262 --*/
263 {
264 CHAR8 *Token;
265 CHAR8 Buff[FILE_NAME_SIZE];
266 CHAR8 OrgLine[FILE_NAME_SIZE];
267 CHAR8 Str[FILE_NAME_SIZE];
268 CHAR8 Delimit[] = "=";
269
270 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
271 strcpy (OrgLine, Buff);
272 TrimLine (Buff);
273 if (Buff[0] == 0) {
274 continue;
275 }
276
277 Token = strtok (Buff, Delimit);
278
279 while (Token != NULL) {
280 strcpy (Str, Token);
281 BuildTokenList (Str);
282 Token = strtok (NULL, Delimit);
283 }
284 }
285 }
286
287 EFI_STATUS
288 InitializeComps (
289 VOID
290 )
291 /*++
292
293 Routine Description:
294
295 This function intializes the relevant global variable which is being
296 used to store the information retrieved from INF file. This also initializes
297 the BSF symbol file.
298
299 Arguments:
300
301 None
302
303 Returns:
304
305 EFI_SUCCESS - The function completed successfully
306 EFI_OUT_OF_RESOURCES - Malloc failed.
307
308 --*/
309 {
310
311 FileListPtr = malloc (sizeof (PARSED_BSF_INFO));
312
313 if (FileListPtr == NULL) {
314 return EFI_OUT_OF_RESOURCES;
315 }
316
317 FileListHeadPtr = FileListPtr;
318 memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
319 FileListPtr->NextBsfInfo = NULL;
320
321 remove (BSF_SYM_FILE);
322 return EFI_SUCCESS;
323 }
324
325 VOID
326 ParseAndUpdateComponents (
327 IN PARSED_BSF_INFO *BsfInfo
328 )
329 /*++
330
331 Routine Description:
332
333 This function intializes the relevant global variable which is being
334 used to store the information retrieved from INF file.
335
336 Arguments:
337
338 BsfInfo - A pointer to the BSF Info Structure
339
340
341 Returns:
342
343 None
344
345 --*/
346 {
347 UINT64 StringValue;
348
349 while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
350
351 if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
352 TokenStr++;
353 if (_stricmp (*TokenStr, "F") == 0) {
354 BsfInfo->LocationType = FIRST_VTF;
355 } else if (_stricmp (*TokenStr, "S") == 0) {
356 BsfInfo->LocationType = SECOND_VTF;
357 } else {
358 BsfInfo->LocationType = NONE;
359 printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
360 }
361 } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
362 TokenStr++;
363 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
364 printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
365 return ;
366 }
367
368 BsfInfo->CompType = (UINT8) StringValue;
369 } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
370 TokenStr++;
371 if (_stricmp (*TokenStr, "-") == 0) {
372 BsfInfo->VersionPresent = FALSE;
373 BsfInfo->MajorVer = 0;
374 BsfInfo->MinorVer = 0;
375 } else {
376 BsfInfo->VersionPresent = TRUE;
377 ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
378 }
379 } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
380 TokenStr++;
381 strcpy (BsfInfo->CompBinName, *TokenStr);
382 } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
383 TokenStr++;
384 strcpy (BsfInfo->CompSymName, *TokenStr);
385 } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
386 TokenStr++;
387 if (_stricmp (*TokenStr, "-") == 0) {
388 BsfInfo->PreferredSize = FALSE;
389 BsfInfo->CompSize = 0;
390 } else {
391 BsfInfo->PreferredSize = TRUE;
392 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
393 printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
394 return ;
395 }
396
397 BsfInfo->CompSize = (UINTN) StringValue;
398 }
399
400 } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
401 TokenStr++;
402 if (_stricmp (*TokenStr, "1") == 0) {
403 BsfInfo->CheckSumRequired = 1;
404 } else if (_stricmp (*TokenStr, "0") == 0) {
405 BsfInfo->CheckSumRequired = 0;
406 } else {
407 printf ("\nERROR: Bad information in INF file about Checksum required field");
408 }
409 }
410
411 TokenStr++;
412 if (*TokenStr == NULL) {
413 break;
414 }
415 }
416 }
417
418 VOID
419 InitializeInFileInfo (
420 VOID
421 )
422 /*++
423
424 Routine Description:
425
426 This function intializes the relevant global variable which is being
427 used to store the information retrieved from INF file.
428
429 Arguments:
430
431 NONE
432
433 Returns:
434
435 NONE
436
437 --*/
438 {
439 UINTN SectionOptionFlag;
440 UINTN SectionCompFlag;
441
442 SectionOptionFlag = 0;
443 SectionCompFlag = 0;
444 TokenStr = OrgStrTokPtr;
445 while (*TokenStr != NULL) {
446 if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
447 SectionOptionFlag = 1;
448 SectionCompFlag = 0;
449 }
450
451 if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {
452 if (FileListPtr == NULL) {
453 FileListPtr = FileListHeadPtr;
454 }
455
456 SectionCompFlag = 1;
457 SectionOptionFlag = 0;
458 TokenStr++;
459 }
460
461 if (SectionOptionFlag) {
462 if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
463 *TokenStr++;
464 strcpy (IA32BinFile, *TokenStr);
465 }
466 }
467
468 if (SectionCompFlag) {
469 if (_stricmp (*TokenStr, "COMP_NAME") == 0) {
470 TokenStr++;
471 strcpy (FileListPtr->CompName, *TokenStr);
472 TokenStr++;
473 ParseAndUpdateComponents (FileListPtr);
474 }
475
476 if (*TokenStr != NULL) {
477 FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
478 if (FileListPtr->NextBsfInfo == NULL) {
479 printf ("Error: Out of memory resources.\n");
480 break;
481 }
482 FileListPtr = FileListPtr->NextBsfInfo;
483 memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
484 FileListPtr->NextBsfInfo = NULL;
485 continue;
486 } else {
487 break;
488 }
489 }
490
491 TokenStr++;
492 }
493 }
494
495 EFI_STATUS
496 GetBsfRelatedInfoFromInfFile (
497 IN CHAR8 *FileName
498 )
499 /*++
500
501 Routine Description:
502
503 This function reads the input file, parse it and create a list of tokens
504 which is parsed and used, to intialize the data related to BSF
505
506 Arguments:
507
508 FileName - FileName which needed to be read to parse data
509
510 Returns:
511
512 EFI_ABORTED - Error in opening file
513 EFI_INVALID_PARAMETER - File doesn't contain any valid informations
514 EFI_OUT_OF_RESOURCES - Malloc Failed
515 EFI_SUCCESS - The function completed successfully
516
517 --*/
518 {
519 FILE *Fp;
520 UINTN Index;
521 EFI_STATUS Status;
522
523 Fp = fopen (FileName, "r");
524 if (Fp == NULL) {
525 printf ("\nERROR: Error in opening %s file\n", FileName);
526 return EFI_ABORTED;
527 }
528
529 ValidLineCount (Fp);
530
531 if (ValidLineNum == 0) {
532 printf ("\nERROR: File doesn't contain any valid informations");
533 return EFI_INVALID_PARAMETER;
534 }
535
536 TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
537
538 if (TokenStr == NULL) {
539 return EFI_OUT_OF_RESOURCES;
540 }
541
542 memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
543 OrgStrTokPtr = TokenStr;
544
545 for (Index = 0; Index < (2 * ValidLineNum); Index++) {
546 *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
547
548 if (*TokenStr == NULL) {
549 free (OrgStrTokPtr);
550 return EFI_OUT_OF_RESOURCES;
551 }
552
553 memset (*TokenStr, 0, FILE_NAME_SIZE);
554 // free (*TokenStr);
555 TokenStr++;
556 }
557
558 TokenStr = NULL;
559 TokenStr = OrgStrTokPtr;
560 fseek (Fp, 0L, SEEK_SET);
561
562 Status = InitializeComps ();
563
564 if (Status != EFI_SUCCESS) {
565 free (OrgStrTokPtr);
566 return Status;
567 }
568
569 ParseInputFile (Fp);
570 InitializeInFileInfo ();
571
572 if (Fp) {
573 fclose (Fp);
574 }
575 free (OrgStrTokPtr);
576 return EFI_SUCCESS;
577 }
578
579 VOID
580 GetRelativeAddressInBsfBuffer (
581 IN UINT64 Address,
582 IN OUT UINTN *RelativeAddress,
583 IN LOC_TYPE LocType
584 )
585 /*++
586
587 Routine Description:
588
589 This function checks for the address alignmnet for specified data boundary. In
590 case the address is not aligned, it returns FALSE and the amount of data in
591 terms of byte needed to adjust to get the boundary alignmnet. If data is
592 aligned, TRUE will be returned.
593
594 Arguments:
595
596 Address - The address of the flash map space
597 RelativeAddress - The relative address of the Buffer
598 LocType - The type of the BSF
599
600
601 Returns:
602
603
604 --*/
605 {
606 UINT64 TempAddress;
607 UINT8 *LocalBuff;
608
609 if (LocType == FIRST_VTF) {
610 LocalBuff = (UINT8 *) Bsf1EndBuffer;
611 TempAddress = Fv1EndAddress - Address;
612 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
613 } else {
614 LocalBuff = (UINT8 *) Bsf2EndBuffer;
615 TempAddress = Fv2EndAddress - Address;
616 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
617 }
618 }
619
620 EFI_STATUS
621 GetComponentVersionInfo (
622 IN OUT PARSED_BSF_INFO *BsfInfo,
623 IN UINT8 *Buffer
624 )
625 /*++
626 Routine Description:
627
628 This function will extract the version information from File
629
630 Arguments:
631
632 BsfInfo - A Pointer to the BSF Info Structure
633 Buffer - A Pointer to type UINT8
634
635 Returns:
636
637 EFI_SUCCESS - The function completed successfully
638 EFI_INVALID_PARAMETER - The parameter is invalid
639
640 --*/
641 {
642 UINT16 VersionInfo;
643 EFI_STATUS Status;
644
645 switch (BsfInfo->CompType) {
646
647 case COMP_TYPE_FIT_PAL_A:
648 case COMP_TYPE_FIT_PAL_B:
649 memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));
650 BsfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);
651 BsfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);
652 Status = EFI_SUCCESS;
653 break;
654
655 default:
656 Status = EFI_INVALID_PARAMETER;
657 break;
658 }
659
660 return Status;
661 }
662
663 BOOLEAN
664 CheckAddressAlignment (
665 IN UINT64 Address,
666 IN UINT64 AlignmentData,
667 IN OUT UINT64 *AlignAdjustByte
668 )
669 /*++
670
671 Routine Description:
672
673 This function checks for the address alignmnet for specified data boundary. In
674 case the address is not aligned, it returns FALSE and the amount of data in
675 terms of byte needed to adjust to get the boundary alignmnet. If data is
676 aligned, TRUE will be returned.
677
678 Arguments:
679
680 Address - Pointer to buffer containing byte data of component.
681 AlignmentData - DataSize for which address needed to be aligned
682 AlignAdjustByte - Number of bytes needed to adjust alignment.
683
684 Returns:
685
686 TRUE - Address is aligned to specific data size boundary
687 FALSE - Address in not aligned to specified data size boundary
688 - Add/Subtract AlignAdjustByte to aling the address.
689
690 --*/
691 {
692 //
693 // Check if the assigned address is on address boundary. If not, it will
694 // return the remaining byte required to adjust the address for specified
695 // address boundary
696 //
697 *AlignAdjustByte = (Address % AlignmentData);
698
699 if (*AlignAdjustByte == 0) {
700 return TRUE;
701 } else {
702 return FALSE;
703 }
704 }
705
706 EFI_STATUS
707 GetFitTableStartAddress (
708 IN OUT FIT_TABLE **FitTable
709 )
710 /*++
711
712 Routine Description:
713
714 Get the FIT table start address in BSF Buffer
715
716 Arguments:
717
718 FitTable - Pointer to available fit table where new component can be added
719
720 Returns:
721
722 EFI_SUCCESS - The function completed successfully
723
724 --*/
725 {
726 UINT64 FitTableAdd;
727 UINT64 FitTableAddOffset;
728 UINTN RelativeAddress;
729
730 //
731 // Read the Fit Table address from Itanium-based address map.
732 //
733 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
734
735 //
736 // Translate this Itanium-based address in terms of local buffer address which
737 // contains the image for Boot Strapped File. The relative address will be
738 // the address of fit table BSF buffer.
739 //
740 GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
741 FitTableAdd = *(UINTN *) RelativeAddress;
742
743 //
744 // The FitTableAdd is the extracted Itanium based address pointing to FIT
745 // table. The relative address will return its actual location in BSF
746 // Buffer.
747 //
748 GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
749
750 *FitTable = (FIT_TABLE *) RelativeAddress;
751
752 return EFI_SUCCESS;
753 }
754
755 EFI_STATUS
756 GetNextAvailableFitPtr (
757 IN FIT_TABLE **FitPtr
758 )
759 /*++
760
761 Routine Description:
762
763 Get the FIT table address and locate the free space in fit where we can add
764 new component. In this process, this function locates the fit table using
765 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
766 and locate the available location in FIT table to be used by new components.
767 If there are any Fit table which areg not being used contains ComponentType
768 field as 0x7F. If needed we can change this and spec this out.
769
770 Arguments:
771
772 FitPtr - Pointer to available fit table where new component can be added
773
774 Returns:
775
776 EFI_SUCCESS - The function completed successfully
777
778 --*/
779 {
780 FIT_TABLE *TmpFitPtr;
781 UINT64 FitTableAdd;
782 UINT64 FitTableAddOffset;
783 UINTN Index;
784 UINTN NumFitComponents;
785 UINTN RelativeAddress;
786
787 //
788 // Read the Fit Table address from Itanium-based address map.
789 //
790 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
791
792 //
793 // Translate this Itanium-based address in terms of local buffer address which
794 // contains the image for Boot Strapped File. The relative address will be
795 // the address of fit table BSF buffer.
796 //
797 GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
798 FitTableAdd = *(UINTN *) RelativeAddress;
799
800 //
801 // The FitTableAdd is the extracted Itanium based address pointing to FIT
802 // table. The relative address will return its actual location in BSF
803 // Buffer.
804 //
805 GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
806
807 TmpFitPtr = (FIT_TABLE *) RelativeAddress;
808 NumFitComponents = TmpFitPtr->CompSize;
809
810 for (Index = 0; Index < NumFitComponents; Index++) {
811 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {
812 *FitPtr = TmpFitPtr;
813 break;
814 }
815
816 TmpFitPtr++;
817 }
818
819 return EFI_SUCCESS;
820 }
821
822 INTN
823 CompareItems (
824 IN const VOID *Arg1,
825 IN const VOID *Arg2
826 )
827 /*++
828
829 Routine Description:
830
831 This function is used by qsort to sort the FIT table based upon Component
832 Type in their incresing order.
833
834 Arguments:
835
836 Arg1 - Pointer to Arg1
837 Arg2 - Pointer to Arg2
838
839 Returns:
840
841 None
842
843 --*/
844 {
845 if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
846 return 1;
847 } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
848 return -1;
849 } else {
850 return 0;
851 }
852 }
853
854 VOID
855 SortFitTable (
856 IN VOID
857 )
858 /*++
859
860 Routine Description:
861
862 This function is used by qsort to sort the FIT table based upon Component
863 Type in their incresing order.
864
865 Arguments:
866
867 VOID
868
869 Returns:
870
871 None
872
873 --*/
874 {
875 FIT_TABLE *FitTable;
876 FIT_TABLE *TmpFitPtr;
877 UINTN NumFitComponents;
878 UINTN Index;
879
880 GetFitTableStartAddress (&FitTable);
881 TmpFitPtr = FitTable;
882 NumFitComponents = 0;
883 for (Index = 0; Index < FitTable->CompSize; Index++) {
884 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {
885 NumFitComponents += 1;
886 }
887
888 TmpFitPtr++;
889 }
890
891 qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);
892 }
893
894 VOID
895 UpdateFitEntryForFwVolume (
896 IN UINT64 Size
897 )
898 /*++
899
900 Routine Description:
901
902 This function updates the information about Firmware Volume in FIT TABLE.
903 This FIT table has to be immediately below the PAL_A Start and it contains
904 component type and address information. Other informations can't be
905 created this time so we would need to fix it up..
906
907
908 Arguments:
909
910 Size - Firmware Volume Size
911
912 Returns:
913
914 VOID
915
916 --*/
917 {
918 FIT_TABLE *CompFitPtr;
919 UINTN RelativeAddress;
920
921 //
922 // FV Fit table will be located at PAL_A Startaddress - 16 byte location
923 //
924 Bsf1LastStartAddress -= 0x10;
925 Bsf1TotalSize += 0x10;
926
927 GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
928
929 CompFitPtr = (FIT_TABLE *) RelativeAddress;
930 CompFitPtr->CompAddress = Fv1BaseAddress;
931
932 //
933 // Since we don't have any information about its location in Firmware Volume,
934 // initialize address to 0. This will be updated once Firmware Volume is
935 // being build and its current address will be fixed in FIT table. Currently
936 // we haven't implemented it so far and working on architectural clarafication
937 //
938 //
939 // Firmware Volume Size in 16 byte block
940 //
941 CompFitPtr->CompSize = ((UINT32) Size) / 16;
942
943 //
944 // Since Firmware Volume does not exist by the time we create this FIT info
945 // this should be fixedup from Firmware Volume creation tool. We haven't
946 // worked out a method so far.
947 //
948 CompFitPtr->CompVersion = MAKE_VERSION (0, 0);
949
950 //
951 // Since we don't have any info about this file, we are making sure that
952 // checksum is not needed.
953 //
954 CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);
955
956 //
957 // Since non BSF component will reside outside the BSF, we will not have its
958 // binary image while creating BSF, hence we will not perform checksum at
959 // this time. Once Firmware Volume is being created which will contain this
960 // BSF, it will fix the FIT table for all the non BSF component and hence
961 // checksum
962 //
963 CompFitPtr->CheckSum = 0;
964 }
965
966 EFI_STATUS
967 UpdateFitEntryForNonBSFComp (
968 IN PARSED_BSF_INFO *BsfInfo
969 )
970 /*++
971
972 Routine Description:
973
974 This function updates the information about non BSF component in FIT TABLE.
975 Since non BSF componets binaries are not part of BSF binary, we would still
976 be required to update its location information in Firmware Volume, inside
977 FIT table.
978
979 Arguments:
980
981 BsfInfo - Pointer to BSF Info Structure
982
983 Returns:
984
985 EFI_ABORTED - The function fails to update the component in FIT
986 EFI_SUCCESS - The function completed successfully
987
988 --*/
989 {
990 FIT_TABLE *CompFitPtr;
991
992 //
993 // Scan the FIT table for available space
994 //
995 GetNextAvailableFitPtr (&CompFitPtr);
996 if (CompFitPtr == NULL) {
997 printf ("\nERROR: Can't update this component in FIT");
998 return EFI_ABORTED;
999 }
1000
1001 //
1002 // Since we don't have any information about its location in Firmware Volume,
1003 // initialize address to 0. This will be updated once Firmware Volume is
1004 // being build and its current address will be fixed in FIT table
1005 //
1006 CompFitPtr->CompAddress = 0;
1007 CompFitPtr->CompSize = BsfInfo->CompSize;
1008 CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
1009 CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
1010
1011 //
1012 // Since non BSF component will reside outside the BSF, we will not have its
1013 // binary image while creating BSF, hence we will not perform checksum at
1014 // this time. Once Firmware Volume is being created which will contain this
1015 // BSF, it will fix the FIT table for all the non BSF component and hence
1016 // checksum
1017 //
1018 CompFitPtr->CheckSum = 0;
1019
1020 //
1021 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
1022 // address of Firmware Volume in which this BSF will be attached.
1023 //
1024 if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {
1025 CompFitPtr->CompAddress = Fv1BaseAddress;
1026 }
1027
1028 return EFI_SUCCESS;
1029 }
1030
1031 //
1032 // !!!WARNING
1033 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
1034 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
1035 // CORE moves in Firmware Volume, we would need to modify this function to be
1036 // used with a API which will detect PEICORE component while building Firmware
1037 // Volume and update its entry in FIT table as well as in Itanium address space
1038 // as per Intel?Itanium(TM) SAL address space
1039 //
1040 EFI_STATUS
1041 UpdateEntryPoint (
1042 IN PARSED_BSF_INFO *BsfInfo,
1043 IN UINT64 *CompStartAddress
1044 )
1045 /*++
1046
1047 Routine Description:
1048
1049 This function updated the architectural entry point in IPF, SALE_ENTRY.
1050
1051 Arguments:
1052
1053 BsfInfo - Pointer to BSF Info Structure
1054 CompStartAddress - Pointer to Component Start Address
1055
1056 Returns:
1057
1058 EFI_INVALID_PARAMETER - The parameter is invalid
1059 EFI_SUCCESS - The function completed successfully
1060
1061 --*/
1062 {
1063 UINTN RelativeAddress;
1064 UINT64 SalEntryAdd;
1065 FILE *Fp;
1066 UINTN Offset;
1067
1068 CHAR8 Buff[FILE_NAME_SIZE];
1069 CHAR8 Buff1[10];
1070 CHAR8 Buff2[10];
1071 CHAR8 OffsetStr[30];
1072 CHAR8 Buff3[10];
1073 CHAR8 Buff4[10];
1074 CHAR8 Buff5[10];
1075 CHAR8 Token[50];
1076
1077 Fp = fopen (BsfInfo->CompSymName, "r+b");
1078
1079 if (Fp == NULL) {
1080 printf ("\nERROR: Error in opening file");
1081 return EFI_INVALID_PARAMETER;
1082 }
1083
1084 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
1085 fscanf (
1086 Fp,
1087 "%s %s %s %s %s %s %s",
1088 &Buff1,
1089 &Buff2,
1090 &OffsetStr,
1091 &Buff3,
1092 &Buff4,
1093 &Buff5,
1094 &Token
1095 );
1096 if (_stricmp (Token, "SALE_ENTRY") == 0) {
1097 break;
1098 }
1099 }
1100
1101 Offset = strtoul (OffsetStr, NULL, 16);
1102
1103 *CompStartAddress += Offset;
1104 SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
1105
1106 GetRelativeAddressInBsfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
1107
1108 memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
1109
1110 return EFI_SUCCESS;
1111 }
1112
1113 EFI_STATUS
1114 CreateAndUpdateComponent (
1115 IN PARSED_BSF_INFO *BsfInfo
1116 )
1117 /*++
1118
1119 Routine Description:
1120
1121 This function reads the binary file for each components and update them
1122 in BSF Buffer as well as in FIT table. If the component is located in non
1123 BSF area, only the FIT table address will be updated
1124
1125 Arguments:
1126
1127 BsfInfo - Pointer to Parsed Info
1128
1129 Returns:
1130
1131 EFI_SUCCESS - The function completed successful
1132 EFI_ABORTED - Aborted due to one of the many reasons like:
1133 (a) Component Size greater than the specified size.
1134 (b) Error opening files.
1135
1136 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
1137 EFI_OUT_OF_RESOURCES Memory allocation failure.
1138
1139 --*/
1140 {
1141 EFI_STATUS Status;
1142 UINT64 CompStartAddress;
1143 UINT64 FileSize;
1144 UINT64 NumByteRead;
1145 UINT64 NumAdjustByte;
1146 UINT8 *Buffer;
1147 FILE *Fp;
1148 FIT_TABLE *CompFitPtr;
1149 BOOLEAN Aligncheck;
1150
1151 if (BsfInfo->LocationType == NONE) {
1152 UpdateFitEntryForNonBSFComp (BsfInfo);
1153 return EFI_SUCCESS;
1154 }
1155
1156 Fp = fopen (BsfInfo->CompBinName, "r+b");
1157
1158 if (Fp == NULL) {
1159 printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
1160 return EFI_ABORTED;
1161 }
1162
1163 FileSize = _filelength (fileno (Fp));
1164
1165 if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1166
1167 //
1168 // BUGBUG: Satish to correct
1169 //
1170 FileSize -= SIZE_OF_PAL_HEADER;
1171 }
1172
1173 if (BsfInfo->PreferredSize) {
1174 if (FileSize > BsfInfo->CompSize) {
1175 printf ("\nERROR: The component size is more than specified size");
1176 return EFI_ABORTED;
1177 }
1178
1179 FileSize = BsfInfo->CompSize;
1180 }
1181
1182 Buffer = malloc ((UINTN) FileSize);
1183 if (Buffer == NULL) {
1184 return EFI_OUT_OF_RESOURCES;
1185 }
1186 memset (Buffer, 0, (UINTN) FileSize);
1187
1188 if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
1189
1190 //
1191 // Read first 64 bytes of PAL header and use it to find version info
1192 //
1193 NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1194
1195 //
1196 // PAL header contains the version info. Currently, we will use the header
1197 // to read version info and then discard.
1198 //
1199 if (!BsfInfo->VersionPresent) {
1200 GetComponentVersionInfo (BsfInfo, Buffer);
1201 }
1202 }
1203
1204 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1205 fclose (Fp);
1206
1207 //
1208 // If it is non PAL_B component, pass the entire buffer to get the version
1209 // info and implement any specific case inside GetComponentVersionInfo.
1210 //
1211 if (BsfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
1212 if (!BsfInfo->VersionPresent) {
1213 GetComponentVersionInfo (BsfInfo, Buffer);
1214 }
1215 }
1216
1217 if (BsfInfo->LocationType == SECOND_VTF) {
1218
1219 CompStartAddress = (Bsf2LastStartAddress - FileSize);
1220 } else {
1221 CompStartAddress = (Bsf1LastStartAddress - FileSize);
1222 }
1223
1224 if (BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
1225 Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
1226 } else {
1227 Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
1228 }
1229
1230 if (!Aligncheck) {
1231 CompStartAddress -= NumAdjustByte;
1232 }
1233
1234 if (BsfInfo->LocationType == SECOND_VTF) {
1235 Bsf2LastStartAddress = CompStartAddress;
1236 Bsf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
1237 Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
1238 } else {
1239 Bsf1LastStartAddress = CompStartAddress;
1240 Bsf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
1241 Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
1242 }
1243
1244 if (EFI_ERROR (Status)) {
1245 return EFI_ABORTED;
1246 }
1247
1248 GetNextAvailableFitPtr (&CompFitPtr);
1249
1250 CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
1251 assert ((FileSize % 16) == 0);
1252 CompFitPtr->CompSize = (UINT32) (FileSize / 16);
1253 CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
1254 CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
1255 if (BsfInfo->CheckSumRequired) {
1256 CompFitPtr->CheckSum = 0;
1257 CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
1258 }
1259
1260 //
1261 // Free the buffer
1262 //
1263 if (Buffer) {
1264 free (Buffer);
1265 }
1266
1267 //
1268 // Update the SYM file for this component based on it's start address.
1269 //
1270 Status = UpdateSymFile (CompStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);
1271 if (EFI_ERROR (Status)) {
1272
1273 //
1274 // At this time, SYM files are not required, so continue on error.
1275 //
1276 }
1277
1278 // !!!!!!!!!!!!!!!!!!!!!
1279 // BUGBUG:
1280 // This part of the code is a temporary line since PEICORE is going to be inside
1281 // BSF till we work out how to determine the SALE_ENTRY through it. We will need
1282 // to clarify so many related questions
1283 // !!!!!!!!!!!!!!!!!!!!!!!
1284 if (BsfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
1285 Status = UpdateEntryPoint (BsfInfo, &CompStartAddress);
1286 }
1287
1288 return Status;
1289 }
1290
1291 EFI_STATUS
1292 CreateAndUpdatePAL_A (
1293 IN PARSED_BSF_INFO *BsfInfo
1294 )
1295 /*++
1296
1297 Routine Description:
1298
1299 This function reads the binary file for each components and update them
1300 in BSF Buffer as well as FIT table
1301
1302 Arguments:
1303
1304 BsfInfo - 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 (BsfInfo->CompBinName, "r+b");
1331
1332 if (Fp == NULL) {
1333 printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
1334 return EFI_ABORTED;
1335 }
1336
1337 FileSize = _filelength (fileno (Fp));
1338 FileSize -= SIZE_OF_PAL_HEADER;
1339
1340 if (BsfInfo->PreferredSize) {
1341 if (FileSize > BsfInfo->CompSize) {
1342 printf ("\nERROR: The PAL_A Size is more than specified size");
1343 return EFI_ABORTED;
1344 }
1345
1346 FileSize = BsfInfo->CompSize;
1347 }
1348
1349 Buffer = malloc ((UINTN) FileSize);
1350 if (Buffer == NULL) {
1351 return EFI_OUT_OF_RESOURCES;
1352 }
1353 memset (Buffer, 0, (UINTN) FileSize);
1354
1355 //
1356 // Read, Get version Info and discard the PAL header.
1357 //
1358 NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
1359
1360 //
1361 // Extract the version info from header of PAL_A. Once done, discrad this buffer
1362 //
1363 if (!BsfInfo->VersionPresent) {
1364 GetComponentVersionInfo (BsfInfo, Buffer);
1365 }
1366
1367 //
1368 // Read PAL_A file in a buffer
1369 //
1370 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
1371 fclose (Fp);
1372
1373 PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);
1374 Bsf1LastStartAddress = PalStartAddress;
1375 Bsf1TotalSize += (UINT32) FileSize;
1376 Status = UpdateBsfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
1377
1378 AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
1379 GetRelativeAddressInBsfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
1380 PalFitPtr = (FIT_TABLE *) RelativeAddress;
1381 PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;
1382 assert ((FileSize % 16) == 0);
1383 PalFitPtr->CompSize = (UINT32) (FileSize / 16);
1384 PalFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
1385 PalFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
1386 if (BsfInfo->CheckSumRequired) {
1387 PalFitPtr->CheckSum = 0;
1388 PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
1389 }
1390
1391 if (Buffer) {
1392 free (Buffer);
1393 }
1394
1395 //
1396 // Update the SYM file for this component based on it's start address.
1397 //
1398 Status = UpdateSymFile (PalStartAddress, BSF_SYM_FILE, BsfInfo->CompSymName);
1399 if (EFI_ERROR (Status)) {
1400
1401 //
1402 // At this time, SYM files are not required, so continue on error.
1403 //
1404 }
1405
1406 return Status;
1407 }
1408
1409 EFI_STATUS
1410 CreateFitTableAndInitialize (
1411 IN PARSED_BSF_INFO *BsfInfo
1412 )
1413 /*++
1414
1415 Routine Description:
1416
1417 This function creates and intializes FIT table which would be used to
1418 add component info inside this
1419
1420 Arguments:
1421
1422 BsfInfo - Pointer to Parsed Info
1423
1424 Returns:
1425
1426 EFI_ABORTED - Aborted due to no size information
1427 EFI_SUCCESS - The function completed successfully
1428
1429 --*/
1430 {
1431 UINT64 PalFitTableAdd;
1432 UINT64 FitTableAdd;
1433 UINT64 FitTableAddressOffset;
1434 FIT_TABLE *PalFitPtr;
1435 FIT_TABLE *FitStartPtr;
1436 UINTN NumFitComp;
1437 UINTN RelativeAddress;
1438 UINTN Index;
1439
1440 if (!BsfInfo->PreferredSize) {
1441 printf ("\nERROR: FIT could not be allocated becuase there are no size information");
1442 return EFI_ABORTED;
1443 }
1444
1445 if ((BsfInfo->CompSize % 16) != 0) {
1446 printf ("\nERROR: Invalid Fit Table Size, not multiple of 16 bytes. Please correct the size");
1447 }
1448
1449 PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
1450 GetRelativeAddressInBsfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
1451 PalFitPtr = (FIT_TABLE *) RelativeAddress;
1452 PalFitTableAdd = (PalFitPtr->CompAddress - BsfInfo->CompSize);
1453
1454 FitTableAdd = (PalFitPtr->CompAddress - 0x10) - BsfInfo->CompSize;
1455 FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
1456 GetRelativeAddressInBsfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
1457 *(UINT64 *) RelativeAddress = FitTableAdd;
1458
1459 GetRelativeAddressInBsfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
1460
1461 //
1462 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
1463 //
1464 FitStartPtr = (FIT_TABLE *) RelativeAddress;
1465
1466 strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "
1467 assert (((BsfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
1468 FitStartPtr->CompSize = (BsfInfo->CompSize & 0x00FFFFFF) / 16;
1469 FitStartPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
1470
1471 //
1472 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
1473 // determine what to do for things like the FV component that aren't easily checksummed.
1474 // The checksum will be done once we are done with all the componet update in the FIT
1475 // table
1476 //
1477 FitStartPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
1478
1479 NumFitComp = FitStartPtr->CompSize;
1480
1481 FitStartPtr++;
1482
1483 //
1484 // Intialize remaining FIT table space to UNUSED fit component type
1485 // so that when we need to create a FIT entry for a component, we can
1486 // locate a free one and use it.
1487 //
1488 for (Index = 0; Index < (NumFitComp - 1); Index++) {
1489 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED
1490 FitStartPtr++;
1491 }
1492
1493 Bsf1TotalSize += BsfInfo->CompSize;
1494 Bsf1LastStartAddress -= BsfInfo->CompSize;
1495
1496 return EFI_SUCCESS;
1497 }
1498
1499 EFI_STATUS
1500 WriteBsfBinary (
1501 IN CHAR8 *FileName,
1502 IN UINT32 BsfSize,
1503 IN LOC_TYPE LocType
1504 )
1505 /*++
1506
1507 Routine Description:
1508
1509 Write Firmware Volume from memory to a file.
1510
1511 Arguments:
1512
1513 FileName - Output File Name which needed to be created/
1514 BsfSize - FileSize
1515 LocType - The type of the BSF
1516
1517 Returns:
1518
1519 EFI_ABORTED - Returned due to one of the following resons:
1520 (a) Error Opening File
1521 (b) Failing to copy buffers
1522 EFI_SUCCESS - The fuction completes successfully
1523
1524 --*/
1525 {
1526 FILE *Fp;
1527 UINTN NumByte;
1528 VOID *BsfBuffer;
1529 UINTN RelativeAddress;
1530
1531 if (LocType == FIRST_VTF) {
1532 GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1533 BsfBuffer = (VOID *) RelativeAddress;
1534 } else {
1535 GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1536 BsfBuffer = (VOID *) RelativeAddress;
1537 }
1538
1539 Fp = fopen (FileName, "w+b");
1540 if (Fp == NULL) {
1541 printf ("Error in opening file %s\n", FileName);
1542 return EFI_ABORTED;
1543 }
1544
1545 NumByte = fwrite (BsfBuffer, sizeof (UINT8), (UINTN) BsfSize, Fp);
1546
1547 if (Fp) {
1548 fclose (Fp);
1549 }
1550
1551 if (NumByte != (sizeof (UINT8) * BsfSize)) {
1552 printf ("\nERROR: Could not copy buffer into file %s ", FileName);
1553 return EFI_ABORTED;
1554 }
1555
1556 return EFI_SUCCESS;
1557 }
1558
1559 EFI_STATUS
1560 UpdateBsfBuffer (
1561 IN UINT64 StartAddress,
1562 IN UINT8 *Buffer,
1563 IN UINT64 DataSize,
1564 IN LOC_TYPE LocType
1565 )
1566 /*++
1567
1568 Routine Description:
1569
1570 Update the Firmware Volume Buffer with requested buffer data
1571
1572 Arguments:
1573
1574 StartAddress - StartAddress in buffer. This number will automatically
1575 point to right address in buffer where data needed
1576 to be updated.
1577 Buffer - Buffer pointer from data will be copied to memory mapped buffer.
1578 DataSize - Size of the data needed to be copied.
1579 LocType - The type of the BSF
1580
1581 Returns:
1582
1583 EFI_ABORTED - The input parameter is error
1584 EFI_SUCCESS - The function completed successfully
1585
1586 --*/
1587 {
1588 UINT8 *LocalBufferPtrToWrite;
1589
1590 if (LocType == FIRST_VTF) {
1591 if ((StartAddress | IPF_CACHE_BIT) < (Bsf1LastStartAddress | IPF_CACHE_BIT)) {
1592 printf ("ERROR: Start Address is less then the BSF start address\n");
1593 return EFI_ABORTED;
1594 }
1595
1596 LocalBufferPtrToWrite = (UINT8 *) Bsf1EndBuffer;
1597 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
1598 } else {
1599 if ((StartAddress | IPF_CACHE_BIT) < (Bsf2LastStartAddress | IPF_CACHE_BIT)) {
1600 printf ("ERROR: Start Address is less then the BSF start address\n");
1601 return EFI_ABORTED;
1602 }
1603 LocalBufferPtrToWrite = (UINT8 *) Bsf2EndBuffer;
1604 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
1605 }
1606
1607 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
1608
1609 return EFI_SUCCESS;
1610 }
1611
1612 EFI_STATUS
1613 UpdateFfsHeader (
1614 IN UINT32 TotalBsfSize,
1615 IN LOC_TYPE LocType
1616 )
1617 /*++
1618
1619 Routine Description:
1620
1621 Update the Firmware Volume Buffer with requested buffer data
1622
1623 Arguments:
1624
1625 TotalBsfSize - Size of the BSF
1626 Fileoffset - The start of the file relative to the start of the FV.
1627 LocType - The type of the BSF
1628
1629 Returns:
1630
1631 EFI_SUCCESS - The function completed successfully
1632 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
1633
1634 --*/
1635 {
1636 EFI_FFS_FILE_HEADER *FileHeader;
1637 UINTN RelativeAddress;
1638 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1639
1640 //
1641 // Find the BSF file header location
1642 //
1643 if (LocType == FIRST_VTF) {
1644 GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
1645 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1646 } else {
1647 GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);
1648 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
1649 }
1650
1651 if (FileHeader == NULL) {
1652 return EFI_INVALID_PARAMETER;
1653 }
1654
1655 //
1656 // write header
1657 //
1658 memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
1659 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
1660 FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;
1661 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
1662
1663 //
1664 // Now FileSize includes the EFI_FFS_FILE_HEADER
1665 //
1666 FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
1667 FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
1668 FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);
1669
1670 //
1671 // Fill in checksums and state, all three must be zero for the checksums.
1672 //
1673 FileHeader->IntegrityCheck.Checksum.Header = 0;
1674 FileHeader->IntegrityCheck.Checksum.File = 0;
1675 FileHeader->State = 0;
1676 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
1677 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, TotalBsfSize);
1678 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
1679
1680 return EFI_SUCCESS;
1681 }
1682
1683 EFI_STATUS
1684 ValidateAddressAndSize (
1685 IN UINT64 BaseAddress,
1686 IN UINT64 FwVolSize
1687 )
1688 /*++
1689
1690 Routine Description:
1691
1692 Update the Firmware Volume Buffer with requested buffer data
1693
1694 Arguments:
1695
1696 BaseAddress - Base address for the Fw Volume.
1697
1698 FwVolSize - Total Size of the FwVolume to which BSF will be attached..
1699
1700 Returns:
1701
1702 EFI_SUCCESS - The function completed successfully
1703 EFI_UNSUPPORTED - The input parameter is error
1704
1705 --*/
1706 {
1707 if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
1708 return EFI_SUCCESS;
1709 }
1710
1711 return EFI_UNSUPPORTED;
1712 }
1713
1714 EFI_STATUS
1715 UpdateIA32ResetVector (
1716 IN CHAR8 *FileName,
1717 IN UINT64 FirstFwVSize
1718 )
1719 /*++
1720
1721 Routine Description:
1722
1723 Update the 16 byte IA32 Reset vector to maintain the compatibility
1724
1725 Arguments:
1726
1727 FileName - Binary file name which contains the IA32 Reset vector info..
1728 FirstFwVSize - Total Size of the FwVolume to which BSF will be attached..
1729
1730 Returns:
1731
1732 EFI_SUCCESS - The function completed successfully
1733 EFI_ABORTED - Invalid File Size
1734 EFI_INVALID_PARAMETER - Bad File Name
1735 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1736
1737 --*/
1738 {
1739 UINT8 *Buffer;
1740 UINT8 *LocalBsfBuffer;
1741 UINTN FileSize;
1742 UINTN NumByteRead;
1743 FILE *Fp;
1744
1745 if (!strcmp (FileName, "")) {
1746 return EFI_INVALID_PARAMETER;
1747 }
1748
1749 Fp = fopen (FileName, "r+b");
1750
1751 if (Fp == NULL) {
1752 printf ("\nERROR: Unable to open the file %s", FileName);
1753 }
1754
1755 FileSize = _filelength (fileno (Fp));
1756
1757 if (FileSize > 16) {
1758 return EFI_ABORTED;
1759 }
1760
1761 Buffer = malloc (FileSize);
1762 if (Buffer == NULL) {
1763 return EFI_OUT_OF_RESOURCES;
1764 }
1765
1766 NumByteRead = fread (Buffer, sizeof (UINT8), FileSize, Fp);
1767
1768 LocalBsfBuffer = (UINT8 *) Bsf1EndBuffer - SIZE_IA32_RESET_VECT;
1769 memcpy (LocalBsfBuffer, Buffer, FileSize);
1770
1771 if (Buffer) {
1772 free (Buffer);
1773 }
1774
1775 return EFI_SUCCESS;
1776 }
1777
1778 VOID
1779 CleanUpMemory (
1780 VOID
1781 )
1782 /*++
1783
1784 Routine Description:
1785
1786 This function cleans up any allocated buffer
1787
1788 Arguments:
1789
1790 NONE
1791
1792 Returns:
1793
1794 NONE
1795
1796 --*/
1797 {
1798 PARSED_BSF_INFO *TempFileListPtr;
1799
1800 if (Bsf1Buffer) {
1801 free (Bsf1Buffer);
1802 }
1803
1804 if (Bsf2Buffer) {
1805 free (Bsf2Buffer);
1806 }
1807
1808 //
1809 // Cleanup the buffer which was allocated to read the file names from FV.INF
1810 //
1811 FileListPtr = FileListHeadPtr;
1812 while (FileListPtr != NULL) {
1813 TempFileListPtr = FileListPtr->NextBsfInfo;
1814 free (FileListPtr);
1815 FileListPtr = TempFileListPtr;
1816 }
1817 }
1818
1819 EFI_STATUS
1820 ProcessAndCreateBsf (
1821 IN UINT64 Size
1822 )
1823 /*++
1824
1825 Routine Description:
1826
1827 This function process the link list created during INF file parsing
1828 and create component in BSF and updates its info in FIT table
1829
1830 Arguments:
1831
1832 Size - Size of the Firmware Volume of which, this BSF belongs to.
1833
1834 Returns:
1835
1836 EFI_UNSUPPORTED - Unknown FIT type
1837 EFI_SUCCESS - The function completed successfully
1838
1839 --*/
1840 {
1841 EFI_STATUS Status;
1842 PARSED_BSF_INFO *ParsedInfoPtr;
1843
1844 Status = EFI_SUCCESS;
1845
1846 ParsedInfoPtr = FileListHeadPtr;
1847
1848 while (ParsedInfoPtr != NULL) {
1849
1850 switch (ParsedInfoPtr->CompType) {
1851 //
1852 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
1853 //
1854 case COMP_TYPE_FIT_HEADER:
1855 Status = CreateFitTableAndInitialize (ParsedInfoPtr);
1856 break;
1857
1858 //
1859 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
1860 //
1861 case COMP_TYPE_FIT_PAL_A:
1862 Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
1863
1864 //
1865 // Based on BSF specification, once the PAL_A component has been written,
1866 // update the Firmware Volume info as FIT table. This will be utilized
1867 // to extract the Firmware Volume Start address where this BSF will be
1868 // of part.
1869 //
1870 if (Status == EFI_SUCCESS) {
1871 UpdateFitEntryForFwVolume (Size);
1872 }
1873 break;
1874
1875 case COMP_TYPE_FIT_FV_BOOT:
1876 //
1877 // Since FIT entry for Firmware Volume has been created and it is
1878 // located at (PAL_A start - 16 byte). So we will not process any
1879 // Firmware Volume related entry from INF file
1880 //
1881 Status = EFI_SUCCESS;
1882 break;
1883
1884 default:
1885 //
1886 // Any other component type should be handled here. This will create the
1887 // image in specified BSF and create appropriate entry about this
1888 // component in FIT Entry.
1889 //
1890 Status = CreateAndUpdateComponent (ParsedInfoPtr);
1891 if (EFI_ERROR (Status)) {
1892 printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
1893 }
1894 break;
1895 }
1896
1897 ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
1898 }
1899
1900 return Status;
1901 }
1902
1903 EFI_STATUS
1904 GenerateBsfImage (
1905 IN UINT64 StartAddress1,
1906 IN UINT64 Size1,
1907 IN UINT64 StartAddress2,
1908 IN UINT64 Size2
1909 )
1910 /*++
1911
1912 Routine Description:
1913
1914 This is the main function which will be called from application.
1915
1916 Arguments:
1917
1918 StartAddress1 - The start address of the first BSF
1919 Size1 - The size of the first BSF
1920 StartAddress2 - The start address of the second BSF
1921 Size2 - The size of the second BSF
1922
1923 Returns:
1924
1925 EFI_OUT_OF_RESOURCES - Can not allocate memory
1926 The return value can be any of the values
1927 returned by the calls to following functions:
1928 GetBsfRelatedInfoFromInfFile
1929 ProcessAndCreateBsf
1930 UpdateIA32ResetVector
1931 UpdateFfsHeader
1932 WriteBsfBinary
1933
1934 --*/
1935 {
1936 EFI_STATUS Status;
1937 CHAR8 OutFileName1[FILE_NAME_SIZE];
1938 CHAR8 OutFileName2[FILE_NAME_SIZE];
1939 BOOLEAN SecondBSF;
1940
1941 Status = EFI_UNSUPPORTED;
1942
1943 if (StartAddress2 == 0) {
1944 SecondBSF = FALSE;
1945 } else {
1946 SecondBSF = TRUE;
1947 }
1948 Fv1BaseAddress = StartAddress1;
1949 Fv1EndAddress = Fv1BaseAddress + Size1;
1950
1951 memset (OutFileName1, 0, FILE_NAME_SIZE);
1952 sprintf (
1953 OutFileName1,
1954 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
1955 Bsf1NameGuid.Data1,
1956 Bsf1NameGuid.Data2,
1957 Bsf1NameGuid.Data3,
1958 Bsf1NameGuid.Data4[0],
1959 Bsf1NameGuid.Data4[1],
1960 Bsf1NameGuid.Data4[2],
1961 Bsf1NameGuid.Data4[3],
1962 Bsf1NameGuid.Data4[4],
1963 Bsf1NameGuid.Data4[5],
1964 Bsf1NameGuid.Data4[6],
1965 Bsf1NameGuid.Data4[7],
1966 BSF_OUTPUT_FILE
1967 );
1968
1969 //
1970 // The image buffer for the First BSF
1971 //
1972 Bsf1Buffer = malloc ((UINTN) Size1);
1973 if (Bsf1Buffer == NULL) {
1974 printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
1975 return EFI_OUT_OF_RESOURCES;
1976 }
1977 memset (Bsf1Buffer, 0x00, (UINTN) Size1);
1978 Bsf1EndBuffer = (UINT8 *) Bsf1Buffer + Size1;
1979 Bsf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
1980
1981 if (SecondBSF) {
1982 Fv2BaseAddress = StartAddress2;
1983 Fv2EndAddress = Fv2BaseAddress + Size2;
1984
1985 memset (OutFileName2, 0, FILE_NAME_SIZE);
1986 sprintf (
1987 OutFileName2,
1988 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
1989 Bsf2NameGuid.Data1,
1990 Bsf2NameGuid.Data2,
1991 Bsf2NameGuid.Data3,
1992 Bsf2NameGuid.Data4[0],
1993 Bsf2NameGuid.Data4[1],
1994 Bsf2NameGuid.Data4[2],
1995 Bsf2NameGuid.Data4[3],
1996 Bsf2NameGuid.Data4[4],
1997 Bsf2NameGuid.Data4[5],
1998 Bsf2NameGuid.Data4[6],
1999 Bsf2NameGuid.Data4[7],
2000 BSF_OUTPUT_FILE
2001 );
2002
2003 //
2004 // The image buffer for the second BSF
2005 //
2006 Bsf2Buffer = malloc ((UINTN) Size2);
2007 if (Bsf2Buffer == NULL) {
2008 printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
2009 return EFI_OUT_OF_RESOURCES;
2010 }
2011 memset (Bsf2Buffer, 0x00, (UINTN) Size2);
2012 Bsf2EndBuffer = (UINT8 *) Bsf2Buffer + Size2;
2013 Bsf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
2014 }
2015
2016 Status = GetBsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
2017 if (Status != EFI_SUCCESS) {
2018 printf ("\nERROR: Error in parsing input file");
2019 CleanUpMemory ();
2020 return Status;
2021 }
2022
2023 Status = ProcessAndCreateBsf (Size1);
2024 if (Status != EFI_SUCCESS) {
2025 CleanUpMemory ();
2026 return Status;
2027 }
2028
2029 Status = UpdateIA32ResetVector (IA32BinFile, Bsf1TotalSize);
2030 if (Status != EFI_SUCCESS) {
2031 CleanUpMemory ();
2032 return Status;
2033 }
2034
2035 //
2036 // Re arrange the FIT Table for Ascending order of their FIT Type..
2037 //
2038 SortFitTable ();
2039
2040 //
2041 // All components have been updated in FIT table. Now perform the FIT table
2042 // checksum. The following function will check if Checksum is required,
2043 // if yes, then it will perform the checksum otherwise not.
2044 //
2045 CalculateFitTableChecksum ();
2046
2047 //
2048 // Write the FFS header
2049 //
2050 Bsf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
2051 Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
2052 Status = UpdateFfsHeader (Bsf1TotalSize, FIRST_VTF);
2053 if (Status != EFI_SUCCESS) {
2054 CleanUpMemory ();
2055 return Status;
2056 }
2057 //
2058 // Update the BSF buffer into specified BSF binary file
2059 //
2060 Status = WriteBsfBinary (OutFileName1, Bsf1TotalSize, FIRST_VTF);
2061
2062 if (SecondBSF) {
2063 Bsf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
2064 Bsf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
2065 Status = UpdateFfsHeader (Bsf2TotalSize, SECOND_VTF);
2066 if (Status != EFI_SUCCESS) {
2067 CleanUpMemory ();
2068 return Status;
2069 }
2070
2071 //
2072 // Update the BSF buffer into specified BSF binary file
2073 //
2074 Status = WriteBsfBinary (OutFileName2, Bsf2TotalSize, SECOND_VTF);
2075 }
2076
2077 CleanUpMemory ();
2078 printf ("\n");
2079
2080 return Status;
2081 }
2082
2083 EFI_STATUS
2084 PeimFixupInFitTable (
2085 IN UINT64 StartAddress
2086 )
2087 /*++
2088
2089 Routine Description:
2090
2091 This function is an entry point to fixup SAL-E entry point.
2092
2093 Arguments:
2094
2095 StartAddress - StartAddress for PEIM.....
2096
2097 Returns:
2098
2099 EFI_SUCCESS - The function completed successfully
2100 EFI_ABORTED - Error Opening File
2101 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
2102
2103 --*/
2104 {
2105 EFI_STATUS Status;
2106 FILE *Fp;
2107 UINT64 *StartAddressPtr;
2108 UINTN FirstFwVSize;
2109 UINTN NumByte;
2110 CHAR8 OutFileName1[FILE_NAME_SIZE];
2111
2112 StartAddressPtr = malloc (sizeof (UINT64));
2113 if (StartAddressPtr == NULL) {
2114 return EFI_OUT_OF_RESOURCES;
2115 }
2116 *StartAddressPtr = StartAddress;
2117
2118 memset (OutFileName1, 0, FILE_NAME_SIZE);
2119
2120 sprintf (
2121 OutFileName1,
2122 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
2123 Bsf1NameGuid.Data1,
2124 Bsf1NameGuid.Data2,
2125 Bsf1NameGuid.Data3,
2126 Bsf1NameGuid.Data4[0],
2127 Bsf1NameGuid.Data4[1],
2128 Bsf1NameGuid.Data4[2],
2129 Bsf1NameGuid.Data4[3],
2130 Bsf1NameGuid.Data4[4],
2131 Bsf1NameGuid.Data4[5],
2132 Bsf1NameGuid.Data4[6],
2133 Bsf1NameGuid.Data4[7],
2134 BSF_OUTPUT_FILE
2135 );
2136
2137 Fp = fopen (OutFileName1, "r+b");
2138
2139 if (Fp == NULL) {
2140 printf ("\nERROR: Error opening file ");
2141 if (StartAddressPtr) {
2142 free (StartAddressPtr);
2143 }
2144
2145 return EFI_ABORTED;
2146 }
2147
2148 FirstFwVSize = _filelength (fileno (Fp));
2149 fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);
2150 NumByte = fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);
2151
2152 if (Fp) {
2153 fclose (Fp);
2154 }
2155
2156 if (StartAddressPtr) {
2157 free (StartAddressPtr);
2158 }
2159
2160 printf ("\n");
2161 Status = EFI_SUCCESS;
2162 return Status;
2163 }
2164
2165 EFI_STATUS
2166 UpdateSymFile (
2167 IN UINT64 BaseAddress,
2168 IN CHAR8 *DestFileName,
2169 IN CHAR8 *SourceFileName
2170 )
2171 /*++
2172
2173 Routine Description:
2174
2175 This function adds the SYM tokens in the source file to the destination file.
2176 The SYM tokens are updated to reflect the base address.
2177
2178 Arguments:
2179
2180 BaseAddress - The base address for the new SYM tokens.
2181 DestFileName - The destination file.
2182 SourceFileName - The source file.
2183
2184 Returns:
2185
2186 EFI_SUCCESS - The function completed successfully.
2187 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2188 EFI_ABORTED - An error occurred.
2189
2190 --*/
2191 {
2192 FILE *SourceFile;
2193 FILE *DestFile;
2194 CHAR8 Buffer[_MAX_PATH];
2195 CHAR8 Type[_MAX_PATH];
2196 CHAR8 Address[_MAX_PATH];
2197 CHAR8 Section[_MAX_PATH];
2198 CHAR8 Token[_MAX_PATH];
2199 CHAR8 BaseToken[_MAX_PATH];
2200 UINT64 TokenAddress;
2201 long StartLocation;
2202
2203 //
2204 // Verify input parameters.
2205 //
2206 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
2207 return EFI_INVALID_PARAMETER;
2208 }
2209
2210 //
2211 // Open the source file
2212 //
2213 SourceFile = fopen (SourceFileName, "r");
2214 if (SourceFile == NULL) {
2215
2216 //
2217 // SYM files are not required.
2218 //
2219 return EFI_SUCCESS;
2220 }
2221
2222 //
2223 // Use the file name minus extension as the base for tokens
2224 //
2225 strcpy (BaseToken, SourceFileName);
2226 strtok (BaseToken, ". \t\n");
2227 strcat (BaseToken, "__");
2228
2229 //
2230 // Open the destination file
2231 //
2232 DestFile = fopen (DestFileName, "a+");
2233 if (DestFile == NULL) {
2234 fclose (SourceFile);
2235 return EFI_ABORTED;
2236 }
2237
2238 //
2239 // If this is the beginning of the output file, write the symbol format info.
2240 //
2241 if (fseek (DestFile, 0, SEEK_END) != 0) {
2242 fclose (SourceFile);
2243 fclose (DestFile);
2244 return EFI_ABORTED;
2245 }
2246
2247 StartLocation = ftell (DestFile);
2248
2249 if (StartLocation == 0) {
2250 fprintf (DestFile, "TEXTSYM format | V1.0\n");
2251 } else if (StartLocation == -1) {
2252 fclose (SourceFile);
2253 fclose (DestFile);
2254 return EFI_ABORTED;
2255 }
2256
2257 //
2258 // Read the first line
2259 //
2260 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
2261 Buffer[0] = 0;
2262 }
2263
2264 //
2265 // Make sure it matches the expected sym format
2266 //
2267 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
2268 fclose (SourceFile);
2269 fclose (DestFile);
2270 return EFI_ABORTED;
2271 }
2272
2273 //
2274 // Read in the file
2275 //
2276 while (feof (SourceFile) == 0) {
2277
2278 //
2279 // Read a line
2280 //
2281 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {
2282
2283 //
2284 // Get the token address
2285 //
2286 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
2287
2288 //
2289 // Add the base address, the size of the FFS file header and the size of the peim header.
2290 //
2291 TokenAddress += BaseAddress &~IPF_CACHE_BIT;
2292
2293 fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);
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 GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
2341 FitTableAdd = *(UINTN *) RelativeAddress;
2342
2343 GetRelativeAddressInBsfBuffer (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 printf (
2380 "%s, EFI 2.0 BootStrap File Generation Utility. Version %i.%i.\n",
2381 UTILITY_NAME,
2382 UTILITY_MAJOR_VERSION,
2383 UTILITY_MINOR_VERSION
2384 );
2385 }
2386
2387 VOID
2388 Usage (
2389 VOID
2390 )
2391 /*++
2392
2393 Routine Description:
2394
2395 Displays the utility usage syntax to STDOUT
2396
2397 Arguments:
2398
2399 None
2400
2401 Returns:
2402
2403 None
2404
2405 --*/
2406 {
2407 Version();
2408
2409 printf (
2410 "\nUsage: %s -B BaseAddress -S FwVolumeSize\n",
2411 UTILITY_NAME
2412 );
2413 printf (" Where:\n");
2414 printf (" BaseAddress is the starting address of Firmware Volume where Boot\n");
2415 printf (" Strapped Image will reside.\n");
2416 printf (" FwVolumeSize is the size of Firmware Volume.\n");
2417 }
2418
2419 EFI_STATUS
2420 main (
2421 IN UINTN argc,
2422 IN CHAR8 **argv
2423 )
2424 /*++
2425
2426 Routine Description:
2427
2428 This utility uses GenBsfImage.dll to build a Boot Strap File Image which will be
2429 part of firmware volume image.
2430
2431 Arguments:
2432
2433 argc - The count of the parameters
2434 argv - The parameters
2435
2436
2437 Returns:
2438
2439 0 - No error conditions detected.
2440 1 - One or more of the input parameters is invalid.
2441 2 - A resource required by the utility was unavailable.
2442 - Most commonly this will be memory allocation or file creation.
2443 3 - GenFvImage.dll could not be loaded.
2444 4 - Error executing the GenFvImage dll.
2445 5 - Now this tool does not support the IA32 platform
2446
2447 --*/
2448 {
2449 UINT8 Index;
2450 UINT64 StartAddress1;
2451 UINT64 StartAddress2;
2452 UINT64 FwVolSize1;
2453 UINT64 FwVolSize2;
2454 BOOLEAN FirstRoundB;
2455 BOOLEAN FirstRoundS;
2456 EFI_STATUS Status;
2457 BOOLEAN IsIA32;
2458
2459 //
2460 // Verify the correct number of IA32 arguments
2461 //
2462 IsIA32 = FALSE;
2463 if (argc == IA32_ARGS) {
2464 //
2465 // Now this tool is not used for IA32 platform, if it will be used in future,
2466 // the IA32-specific functions need to be updated and verified, the updating can
2467 // refer to IPF relevant functions)
2468 //
2469 printf ("ERROR: Now this tool does not support the IA32 platform!\n");
2470 printf ("ERROR: And the IA32-specific functions need to be updated and verified!\n");
2471 return 5;
2472
2473 /*
2474 StartAddress1 = 0;
2475 IsIA32 = TRUE;
2476
2477 //
2478 // Parse the command line arguments
2479 //
2480 for (Index = 1; Index < IA32_ARGS; Index += 2) {
2481
2482 //
2483 // Make sure argument pair begin with - or /
2484 //
2485 if (argv[Index][0] != '-' && argv[Index][0] != '/') {
2486 Usage ();
2487 printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
2488 return 1;
2489 }
2490
2491 //
2492 // Make sure argument specifier is only one letter
2493 //
2494 if (argv[Index][2] != 0) {
2495 Usage ();
2496 printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
2497 return 1;
2498 }
2499
2500 //
2501 // Determine argument to read
2502 //
2503 switch (argv[Index][1]) {
2504
2505 case 't':
2506 case 'T':
2507 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
2508 if (Status != EFI_SUCCESS) {
2509 printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
2510 return 1;
2511 }
2512 break;
2513
2514 default:
2515 Usage ();
2516 printf ("Unrecognized IA32 argument \"%s\".\n", argv[Index]);
2517 IsIA32 = FALSE;
2518 break;
2519 }
2520 }
2521
2522 if (IsIA32) {
2523 //
2524 // Call the GenBsfImage
2525 //
2526 Status = Generate32BsfImage (StartAddress1);
2527
2528 if (EFI_ERROR(Status)) {
2529 switch (Status) {
2530
2531 case EFI_INVALID_PARAMETER:
2532 printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
2533 break;
2534
2535 case EFI_ABORTED:
2536 printf ("\nERROR: Error detected while creating the file image.\n");
2537 break;
2538
2539 case EFI_OUT_OF_RESOURCES:
2540 printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
2541 break;
2542
2543 case EFI_VOLUME_CORRUPTED:
2544 printf ("\nERROR: No base address was specified \n");
2545 break;
2546
2547 default:
2548 printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
2549 break;
2550 }
2551 return 2;
2552 }
2553
2554 return 0;
2555 }
2556 */
2557 }
2558
2559 //
2560 // Verify the correct number of arguments
2561 //
2562 if (argc == 1) {
2563 Usage();
2564 return 1;
2565 }
2566
2567 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
2568 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
2569 Usage();
2570 return 1;
2571 }
2572
2573 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
2574 Version();
2575 return 1;
2576 }
2577
2578 if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {
2579 Usage ();
2580 return 1;
2581 }
2582
2583 //
2584 // Initialize variables
2585 //
2586 StartAddress1 = 0;
2587 StartAddress2 = 0;
2588 FwVolSize1 = 0;
2589 FwVolSize2 = 0;
2590 FirstRoundB = TRUE;
2591 FirstRoundS = TRUE;
2592
2593 //
2594 // Parse the command line arguments
2595 //
2596 for (Index = 1; Index < argc; Index += 2) {
2597
2598 //
2599 // Make sure argument pair begin with - or /
2600 //
2601 if (argv[Index][0] != '-' && argv[Index][0] != '/') {
2602 Usage ();
2603 printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
2604 return 1;
2605 }
2606
2607 //
2608 // Make sure argument specifier is only one letter
2609 //
2610 if (argv[Index][2] != 0) {
2611 Usage ();
2612 printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
2613 return 1;
2614 }
2615
2616 //
2617 // Determine argument to read
2618 //
2619 switch (argv[Index][1]) {
2620
2621 case 'B':
2622 case 'b':
2623 if (FirstRoundB) {
2624 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
2625 FirstRoundB = FALSE;
2626 } else {
2627 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
2628 }
2629
2630 if (Status != EFI_SUCCESS) {
2631 printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
2632 return 1;
2633 }
2634 break;
2635
2636 case 'S':
2637 case 's':
2638 if (FirstRoundS) {
2639 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
2640 FirstRoundS = FALSE;
2641 } else {
2642 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
2643 }
2644
2645 if (Status != EFI_SUCCESS) {
2646 printf ("\nERROR: Bad size \"%s\"\n", argv[Index + 1]);
2647 return 1;
2648 }
2649 break;
2650
2651 default:
2652 Usage ();
2653 printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
2654 return 1;
2655 break;
2656 }
2657 }
2658
2659 //
2660 // Call the GenBsfImage
2661 //
2662 Status = GenerateBsfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2);
2663
2664 if (EFI_ERROR (Status)) {
2665 switch (Status) {
2666
2667 case EFI_INVALID_PARAMETER:
2668 printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
2669 break;
2670
2671 case EFI_ABORTED:
2672 printf ("\nERROR: Error detected while creating the file image.\n");
2673 break;
2674
2675 case EFI_OUT_OF_RESOURCES:
2676 printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
2677 break;
2678
2679 case EFI_VOLUME_CORRUPTED:
2680 printf ("\nERROR: No base address was specified \n");
2681 break;
2682
2683 default:
2684 printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
2685 break;
2686 }
2687 return 2;
2688 }
2689 return 0;
2690 }
2691
2692 EFI_STATUS
2693 Generate32BsfImage (
2694 IN UINT64 BootFileStartAddress
2695 )
2696 /*++
2697
2698 Routine Description:
2699
2700 This is the main IA32 function which will be called from application.
2701 (Now this tool is not used for IA32 platform, if it will be used in future,
2702 the relative functions need to be updated, the updating can refer to IPF
2703 functions)
2704
2705 Arguments:
2706
2707 BootFileStartAddress - Top Address of Boot File
2708
2709 Returns:
2710
2711 The return value can be any of the values
2712 returned by the calls to following functions:
2713 Get32BsfRelatedInfoFromInfFile
2714 CreateBsfBuffer
2715 ProcessAndCreate32Bsf
2716 Update32FfsHeader
2717 WriteBsfBinary
2718
2719 --*/
2720 {
2721 EFI_STATUS Status;
2722 UINT32 BsfSize;
2723 CHAR8 OutFileName[FILE_NAME_SIZE];
2724
2725 EFI_GUID BsfNameGuid = EFI_IA32_BOOT_STRAP_GUID;
2726
2727 Status = EFI_UNSUPPORTED;
2728
2729 memset (OutFileName, 0, FILE_NAME_SIZE);
2730
2731 sprintf (
2732 OutFileName, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
2733 BsfNameGuid.Data1,
2734 BsfNameGuid.Data2,
2735 BsfNameGuid.Data3,
2736 BsfNameGuid.Data4[0],
2737 BsfNameGuid.Data4[1],
2738 BsfNameGuid.Data4[2],
2739 BsfNameGuid.Data4[3],
2740 BsfNameGuid.Data4[4],
2741 BsfNameGuid.Data4[5],
2742 BsfNameGuid.Data4[6],
2743 BsfNameGuid.Data4[7],
2744 BSF_OUTPUT_FILE
2745 );
2746
2747
2748 Status = Get32BsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
2749
2750 if (Status != EFI_SUCCESS) {
2751 printf ("\nERROR: Error in parsing input file");
2752 CleanUpMemory ();
2753 return Status;
2754 }
2755
2756 if (GetTotal32BsfSize (&BsfSize) == EFI_SUCCESS) {
2757 Bsf1Buffer = malloc ((UINTN) BsfSize);
2758 if (Bsf1Buffer == NULL) {
2759 printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
2760 CleanUpMemory ();
2761 return EFI_OUT_OF_RESOURCES;
2762 }
2763 memset (Bsf1Buffer, 0x00, (UINTN) BsfSize);
2764 } else {
2765 printf ("\nERROR: Could not get BSF size.");
2766 CleanUpMemory ();
2767 return EFI_ABORTED;
2768 }
2769
2770 //
2771 //VTF must align properly
2772 //
2773 Bsf1LastStartAddress = BootFileStartAddress - BsfSize;
2774 Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
2775 BsfSize = (UINT32)BootFileStartAddress - (UINT32)Bsf1LastStartAddress;
2776 Bsf1LastStartAddress = BsfSize;
2777 BufferToTop = (UINT32)BootFileStartAddress - BsfSize;
2778
2779 Status = ProcessAndCreate32Bsf (BsfSize);
2780
2781 if (Status != EFI_SUCCESS) {
2782 CleanUpMemory();
2783 return Status;
2784 }
2785
2786 //
2787 // Write the FFS header
2788 //
2789 Status = Update32FfsHeader (BsfSize);
2790
2791 if (Status != EFI_SUCCESS) {
2792 CleanUpMemory();
2793 return Status;
2794 }
2795
2796 //
2797 // Calculate the Start address of this BSF
2798 //
2799 Bsf1Buffer = (UINT8 *)Bsf1Buffer + Bsf1LastStartAddress;
2800
2801 //
2802 // Update the BSF buffer into specified BSF binary file
2803 //
2804 Status = WriteBsfBinary (OutFileName, BsfSize - (UINT32)Bsf1LastStartAddress, FIRST_VTF);
2805
2806 if (Status != EFI_SUCCESS) {
2807 CleanUpMemory();
2808 return Status;
2809 }
2810
2811 Status = Write32SoftFit (IA32_SOFT_FIT, FileListHeadPtr);
2812
2813 if (Status != EFI_SUCCESS) {
2814 CleanUpMemory();
2815 return Status;
2816 }
2817
2818 CleanUpMemory ();
2819 printf ("\n");
2820
2821 return Status;
2822 }
2823
2824 EFI_STATUS
2825 GetTotal32BsfSize(
2826 IN UINT32 *BsfSize
2827 )
2828 /*++
2829
2830 Routine Description:
2831
2832 This function calculates total size for IA32 BSF which would be needed to create
2833 the buffer. This will be done using Passed Info link list and looking for the
2834 size of the components which belong to BSF. The addtional file header is accounted.
2835
2836 Arguments:
2837
2838 BSFSize - Pointer to the size of IA32 BSF
2839
2840 Returns:
2841
2842 EFI_ABORTED - Returned due to one of the following resons:
2843 (a) Error Opening File
2844 EFI_SUCCESS - The fuction completes successfully
2845
2846 --*/
2847 {
2848 PARSED_BSF_INFO *BsfInfo;
2849 FILE *Fp;
2850 UINT32 Alignment;
2851
2852 *BsfSize = 0;
2853 Alignment = 0;
2854
2855 BsfInfo = FileListHeadPtr;
2856
2857 while (BsfInfo != NULL) {
2858 if (BsfInfo->LocationType != SECOND_VTF) {
2859
2860 if ( BsfInfo->Align ) {
2861 //
2862 // Create additional align to compensate for component boundary requirements
2863 //
2864 Alignment = 1 << BsfInfo->Align;
2865 *BsfSize += Alignment;
2866 }
2867
2868 if (BsfInfo->PreferredSize) {
2869 *BsfSize += BsfInfo->CompSize;
2870 } else {
2871 Fp = fopen (BsfInfo->CompBinName,"r+b");
2872
2873 if (Fp == NULL) {
2874 printf ("\nERROR: Error in opening file %s", BsfInfo->CompBinName);
2875 return EFI_ABORTED;
2876 }
2877
2878 *BsfSize += _filelength (fileno (Fp));
2879
2880 if (Fp) {
2881 fclose (Fp);
2882 }
2883 }
2884 }
2885 BsfInfo = BsfInfo->NextBsfInfo;
2886 }
2887
2888 //
2889 // Add file header space
2890 //
2891 *BsfSize += sizeof (EFI_FFS_FILE_HEADER);
2892
2893 //
2894 // Create additional to IA32 Seccore section header
2895 //
2896 *BsfSize += sizeof (EFI_COMMON_SECTION_HEADER);
2897
2898 return EFI_SUCCESS;
2899 }
2900
2901 EFI_STATUS
2902 ProcessAndCreate32Bsf (
2903 IN UINT64 Size
2904 )
2905 /*++
2906
2907 Routine Description:
2908
2909 This function process the link list created during INF file parsing
2910 and create component in IA32 BSF
2911
2912 Arguments:
2913
2914 Size - Size of the Firmware Volume of which, this BSF belongs to.
2915
2916 Returns:
2917
2918 EFI_UNSUPPORTED - Unknown component type
2919 EFI_SUCCESS - The function completed successfully
2920
2921 --*/
2922 {
2923 EFI_STATUS Status;
2924 PARSED_BSF_INFO *ParsedInfoPtr;
2925
2926 Status = EFI_SUCCESS;
2927
2928 ParsedInfoPtr = FileListHeadPtr;
2929
2930 while (ParsedInfoPtr != NULL) {
2931
2932 switch (ParsedInfoPtr->CompType) {
2933
2934 case COMP_TYPE_SECCORE:
2935 Status = CreateAndUpdateSeccore (ParsedInfoPtr);
2936 break;
2937
2938 default:
2939 //
2940 // Any other component type should be handled here. This will create the
2941 // image in specified BSF
2942 //
2943 Status = CreateAndUpdate32Component (ParsedInfoPtr);
2944 if (EFI_ERROR(Status)) {
2945 printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
2946 }
2947 break;
2948 }
2949
2950 ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
2951 }
2952
2953 return Status;
2954 }
2955
2956 EFI_STATUS
2957 CreateAndUpdateSeccore (
2958 IN PARSED_BSF_INFO *BsfInfo
2959 )
2960 /*++
2961
2962 Routine Description:
2963
2964 This function reads the binary file for seccore and update them
2965 in IA32 BSF Buffer
2966
2967 Arguments:
2968
2969 BsfInfo - Pointer to Parsed Info
2970
2971 Returns:
2972
2973 EFI_ABORTED - Due to one of the following reasons:
2974 (a)Error Opening File
2975 (b)The PAL_A Size is more than specified size status
2976 One of the values mentioned below returned from
2977 call to UpdateSymFile
2978 EFI_SUCCESS - The function completed successfully.
2979 EFI_INVALID_PARAMETER - One of the input parameters was invalid.
2980 EFI_ABORTED - An error occurred.UpdateSymFile
2981 EFI_OUT_OF_RESOURCES - Memory allocation failed.
2982
2983 --*/
2984 {
2985 UINT8 *SecbinStartAddress;
2986 UINT8 *SecfileStartAddress;
2987 UINT32 FileSize;
2988 UINT64 NumByteRead;
2989 UINT8 *Buffer;
2990 FILE *Fp;
2991 UINT64 TotalLength;
2992 EFI_COMMON_SECTION_HEADER *SecHeader;
2993
2994 Fp = fopen (BsfInfo->CompBinName, "r+b");
2995
2996 if (Fp == NULL) {
2997 printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
2998 return EFI_ABORTED;
2999 }
3000
3001 FileSize = _filelength (fileno (Fp));
3002
3003 if (BsfInfo->PreferredSize) {
3004 if (FileSize > BsfInfo->CompSize) {
3005 printf("\nERROR: The Seccore Size is more than specified size");
3006 return EFI_ABORTED;
3007 }
3008
3009 FileSize = BsfInfo->CompSize;
3010 }
3011
3012 BsfInfo->CompSize = FileSize;
3013
3014 Buffer = malloc ((UINTN) FileSize);
3015 if (Buffer == NULL) {
3016 return EFI_OUT_OF_RESOURCES;
3017 }
3018 memset (Buffer, 0, (UINTN) FileSize);
3019
3020 //
3021 // Read seccore in a buffer
3022 //
3023 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
3024 fclose (Fp);
3025
3026 SecfileStartAddress = (UINT8 *) Bsf1Buffer + Bsf1LastStartAddress - FileSize - sizeof (EFI_COMMON_SECTION_HEADER);
3027 if (SecfileStartAddress == NULL) {
3028 return EFI_INVALID_PARAMETER;
3029 }
3030
3031 SecbinStartAddress = SecfileStartAddress + sizeof (EFI_COMMON_SECTION_HEADER);
3032
3033 BsfInfo->CompPreferredAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
3034
3035 //
3036 // write section header
3037 //
3038 memset (SecfileStartAddress, 0, sizeof (EFI_COMMON_SECTION_HEADER));
3039 SecHeader = (EFI_COMMON_SECTION_HEADER *) SecfileStartAddress;
3040 SecHeader->Type = EFI_SECTION_RAW;
3041 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + (UINT64) FileSize;
3042 memcpy (SecHeader->Size, &TotalLength, 3);
3043
3044 //
3045 // write seccore
3046 //
3047 memcpy (SecbinStartAddress, Buffer, (UINTN) FileSize);
3048
3049 if (Buffer) {
3050 free (Buffer);
3051 }
3052
3053 Bsf1LastStartAddress = SecfileStartAddress - (UINT8 *) Bsf1Buffer;
3054
3055 return EFI_SUCCESS;
3056 }
3057
3058 EFI_STATUS
3059 CreateAndUpdate32Component (
3060 IN PARSED_BSF_INFO *BsfInfo
3061 )
3062 /*++
3063
3064 Routine Description:
3065
3066 This function reads the binary file for each components. Add it at aligned address.
3067
3068 Arguments:
3069
3070 BsfInfo - Pointer to Parsed Info
3071
3072 Returns:
3073
3074 EFI_SUCCESS - The function completed successful
3075 EFI_ABORTED - Aborted due to one of the many reasons like:
3076 (a) Component Size greater than the specified size.
3077 (b) Error opening files.
3078 EFI_INVALID_PARAMETER - Value returned from call to UpdateEntryPoint()
3079 EFI_OUT_OF_RESOURCES - Memory allocation failed.
3080
3081 --*/
3082 {
3083 UINT64 CompStartAddress;
3084 UINT32 FileSize;
3085 UINT64 NumByteRead;
3086 UINT8 *Buffer;
3087 FILE *Fp;
3088 UINT8 *LocalBufferPtrToWrite;
3089 UINT64 Alignment;
3090
3091 Fp = fopen (BsfInfo->CompBinName, "r+b");
3092
3093 if (Fp == NULL) {
3094 printf("\nERROR: Opening file %s", BsfInfo->CompBinName);
3095 return EFI_ABORTED;
3096 }
3097
3098 FileSize = _filelength (fileno (Fp));
3099
3100 if (BsfInfo->PreferredSize) {
3101 if (FileSize > BsfInfo->CompSize) {
3102 printf("\nERROR: The component size is more than specified size");
3103 return EFI_ABORTED;
3104 }
3105 FileSize = BsfInfo->CompSize;
3106 }
3107 BsfInfo->CompSize = FileSize;
3108
3109 Buffer = malloc ((UINTN) FileSize);
3110 if (Buffer == NULL) {
3111 return EFI_OUT_OF_RESOURCES;
3112 }
3113 memset (Buffer,0, (UINTN) FileSize);
3114
3115 NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
3116 fclose (Fp);
3117
3118 CompStartAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
3119
3120 if (BsfInfo->Align) {
3121 //
3122 // Create additional align to compensate for component boundary requirements
3123 //
3124 Alignment = 0 - (1 << BsfInfo->Align);
3125 CompStartAddress = CompStartAddress & Alignment;
3126 }
3127
3128 BsfInfo->CompPreferredAddress = CompStartAddress;
3129
3130 //
3131 // write bin
3132 //
3133 LocalBufferPtrToWrite = (UINT8 *) Bsf1Buffer;
3134 Bsf1LastStartAddress = CompStartAddress - BufferToTop;
3135 LocalBufferPtrToWrite += Bsf1LastStartAddress;
3136 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) FileSize);
3137 Bsf1LastStartAddress = CompStartAddress - BufferToTop;
3138
3139 //
3140 // Free the buffer
3141 //
3142 if (Buffer) {
3143 free (Buffer);
3144 }
3145
3146 return EFI_SUCCESS;
3147 }
3148
3149 EFI_STATUS
3150 Update32FfsHeader(
3151 IN UINT32 BsfSize
3152 )
3153 /*++
3154
3155 Routine Description:
3156
3157 Update the Firmware Volume Buffer with requested buffer data
3158
3159 Arguments:
3160
3161 BsfSize - Size of the IA32 BSF
3162
3163 Returns:
3164
3165 EFI_SUCCESS - The function completed successfully
3166 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
3167
3168 --*/
3169 {
3170 EFI_FFS_FILE_HEADER *FileHeader;
3171 UINT32 TotalBsfSize;
3172 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
3173
3174
3175 //
3176 // Find the BSF file header location, the bsf file must be 8 bytes aligned
3177 //
3178 Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
3179 Bsf1LastStartAddress += BufferToTop;
3180 Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
3181 Bsf1LastStartAddress -= BufferToTop;
3182 FileHeader = (EFI_FFS_FILE_HEADER*)((UINT8*)Bsf1Buffer + Bsf1LastStartAddress);
3183
3184 if (FileHeader == NULL) {
3185 return EFI_INVALID_PARAMETER;
3186 }
3187
3188 //
3189 // write header
3190 //
3191 memset (FileHeader, 0, sizeof(EFI_FFS_FILE_HEADER));
3192 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
3193
3194 FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;
3195 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
3196
3197 //
3198 // Now FileSize includes the EFI_FFS_FILE_HEADER
3199 //
3200 TotalBsfSize = BsfSize - (UINT32)Bsf1LastStartAddress;
3201 FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
3202 FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
3203 FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);
3204
3205 //
3206 // Fill in checksums and state, all three must be zero for the checksums.
3207 //
3208 FileHeader->IntegrityCheck.Checksum.Header = 0;
3209 FileHeader->IntegrityCheck.Checksum.File = 0;
3210 FileHeader->State = 0;
3211 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8*) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
3212 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8*) FileHeader, TotalBsfSize);
3213 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
3214
3215 return EFI_SUCCESS;
3216 }
3217
3218 EFI_STATUS
3219 Get32BsfRelatedInfoFromInfFile (
3220 IN CHAR8 *FileName
3221 )
3222 /*++
3223
3224 Routine Description:
3225
3226 This function reads the input file, parse it and create a list of tokens
3227 which is parsed and used, to intialize the data related to IA32 BSF
3228
3229 Arguments:
3230
3231 FileName FileName which needed to be read to parse data
3232
3233 Returns:
3234
3235 EFI_ABORTED Error in opening file
3236 EFI_INVALID_PARAMETER File doesn't contain any valid informations
3237 EFI_OUT_OF_RESOURCES Malloc Failed
3238 EFI_SUCCESS The function completed successfully
3239
3240 --*/
3241 {
3242 FILE *Fp;
3243 UINTN Index;
3244 EFI_STATUS Status;
3245
3246 Fp = fopen (FileName, "r");
3247 if (Fp == NULL) {
3248 printf ("\nERROR: Error in opening %s file\n", FileName);
3249 return EFI_ABORTED;
3250 }
3251
3252 ValidLineCount (Fp);
3253
3254 if (ValidLineNum == 0) {
3255 printf ("\nERROR: File doesn't contain any valid informations");
3256 return EFI_INVALID_PARAMETER;
3257 }
3258
3259 TokenStr = (CHAR8 **)malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
3260
3261 if (TokenStr == NULL) {
3262 return EFI_OUT_OF_RESOURCES;
3263 }
3264 memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
3265 OrgStrTokPtr = TokenStr;
3266
3267 for (Index = 0; Index < (2 * ValidLineNum); Index++) {
3268 *TokenStr = (CHAR8 *)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
3269
3270 if (*TokenStr == NULL) {
3271 free (OrgStrTokPtr);
3272 return EFI_OUT_OF_RESOURCES;
3273 }
3274
3275 memset (*TokenStr, 0, FILE_NAME_SIZE);
3276 // free (*TokenStr);
3277 TokenStr++;
3278 }
3279
3280 TokenStr = NULL;
3281 TokenStr = OrgStrTokPtr;
3282 fseek (Fp, 0L, SEEK_SET);
3283
3284 Status = InitializeComps();
3285
3286 if (Status != EFI_SUCCESS) {
3287 free (TokenStr);
3288 return Status;
3289 }
3290 ParseInputFile (Fp);
3291 Initialize32InFileInfo ();
3292
3293 if (Fp) {
3294 fclose (Fp);
3295 }
3296 free (TokenStr);
3297 return EFI_SUCCESS;
3298 }
3299
3300 VOID
3301 Initialize32InFileInfo (
3302 VOID
3303 )
3304 /*++
3305
3306 Routine Description:
3307
3308 This function intializes the relevant global variable which is being
3309 used to store the information retrieved from IA32 INF file.
3310
3311 Arguments:
3312
3313 NONE
3314
3315 Returns:
3316
3317 NONE
3318
3319 --*/
3320 {
3321 UINTN SectionOptionFlag;
3322 UINTN SectionCompFlag;
3323
3324 SectionOptionFlag =0 ;
3325 SectionCompFlag = 0;
3326 TokenStr = OrgStrTokPtr;
3327 while (*TokenStr != NULL) {
3328 if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
3329 SectionOptionFlag = 1;
3330 SectionCompFlag = 0;
3331 }
3332
3333 if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {
3334 if (FileListPtr == NULL) {
3335 FileListPtr = FileListHeadPtr;
3336 }
3337
3338 SectionCompFlag = 1;
3339 SectionOptionFlag = 0;
3340 TokenStr++;
3341 }
3342
3343 if (SectionOptionFlag) {
3344 if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
3345 *TokenStr++;
3346 strcpy (IA32BinFile, *TokenStr);
3347 }
3348 }
3349
3350 if (SectionCompFlag) {
3351 if (_stricmp (*TokenStr, "COMP_NAME") == 0) {
3352 TokenStr++;
3353 strcpy (FileListPtr->CompName, *TokenStr);
3354 TokenStr++;
3355 ParseAndUpdate32Components (FileListPtr);
3356 }
3357
3358 if (*TokenStr != NULL) {
3359 FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
3360 if (FileListPtr->NextBsfInfo == NULL) {
3361 printf ("Error: Out of memory resources.\n");
3362 break;
3363 }
3364 FileListPtr = FileListPtr->NextBsfInfo;
3365 memset (FileListPtr, 0, sizeof(PARSED_BSF_INFO));
3366 FileListPtr->NextBsfInfo = NULL;
3367 continue;
3368 } else {
3369 break;
3370 }
3371 }
3372
3373 TokenStr++;
3374 }
3375 }
3376
3377 VOID
3378 ParseAndUpdate32Components (
3379 IN PARSED_BSF_INFO *BsfInfo
3380 )
3381 /*++
3382
3383 Routine Description:
3384
3385 This function intializes the relevant global variable which is being
3386 used to store the information retrieved from INF file.
3387
3388 Arguments:
3389
3390 BsfInfo - A pointer to the BSF Info Structure
3391
3392
3393 Returns:
3394
3395 None
3396
3397 --*/
3398 {
3399 UINT64 StringValue;
3400 UINT64 AlignStringValue;
3401
3402 while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
3403
3404 if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
3405 TokenStr++;
3406 if (_stricmp (*TokenStr, "B") == 0) {
3407 BsfInfo->LocationType = FIRST_VTF;
3408 } else if (_stricmp (*TokenStr, "N") == 0) {
3409 BsfInfo->LocationType = SECOND_VTF;
3410 } else {
3411 BsfInfo->LocationType = NONE;
3412 printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
3413 }
3414 } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
3415 TokenStr++;
3416 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
3417 printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
3418 return;
3419 }
3420 BsfInfo->CompType = (UINT8) StringValue;
3421 } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
3422 TokenStr++;
3423 if (_stricmp (*TokenStr, "-") == 0) {
3424 BsfInfo->VersionPresent = FALSE;
3425 BsfInfo->MajorVer = 0;
3426 BsfInfo->MinorVer = 0;
3427 } else {
3428 BsfInfo->VersionPresent = TRUE;
3429 ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
3430 }
3431 } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
3432 TokenStr++;
3433 strcpy (BsfInfo->CompBinName, *TokenStr);
3434 } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
3435 TokenStr++;
3436 strcpy (BsfInfo->CompSymName, *TokenStr);
3437 } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
3438 TokenStr++;
3439 if (_stricmp (*TokenStr, "-") == 0) {
3440 BsfInfo->PreferredSize = FALSE;
3441 BsfInfo->CompSize = 0;
3442 } else {
3443 BsfInfo->PreferredSize = TRUE;
3444 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
3445 printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
3446 return;
3447 }
3448 BsfInfo->CompSize = (UINTN) StringValue;
3449 }
3450
3451 } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
3452 TokenStr++;
3453 if (_stricmp (*TokenStr, "1") == 0) {
3454 BsfInfo->CheckSumRequired = 1;
3455 } else if (_stricmp (*TokenStr, "0") == 0) {
3456 BsfInfo->CheckSumRequired = 0;
3457 } else {
3458 printf ("\nERROR: Bad information in INF file about Checksum required field");
3459 }
3460 } else if (_stricmp (*TokenStr, "COMP_ALIGN") == 0) {
3461 TokenStr++;
3462 if (AsciiStringToUint64 (*TokenStr, FALSE, &AlignStringValue) != EFI_SUCCESS) {
3463 printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
3464 return;
3465 }
3466 if (AlignStringValue >= 0) {
3467 BsfInfo->Align = (UINT32) AlignStringValue;
3468 } else {
3469 printf ("\nERROR: invalid align \"%s\".", AlignStringValue);
3470 return;
3471 }
3472 }
3473 TokenStr++;
3474 if (*TokenStr == NULL) {
3475 break;
3476 }
3477 }
3478 }
3479
3480 EFI_STATUS
3481 Write32SoftFit(
3482 IN CHAR8 *FileName,
3483 IN PARSED_BSF_INFO *BsfInfo
3484 )
3485 /*++
3486
3487 Routine Description:
3488
3489 Write IA32 Firmware Volume component address from memory to a file.
3490
3491 Arguments:
3492
3493 FileName Output File Name which needed to be created/
3494 BsfInfo Parsed info link
3495
3496 Returns:
3497
3498 EFI_ABORTED - Returned due to one of the following resons:
3499 (a) Error Opening File
3500 (b) Failing to copy buffers
3501 EFI_SUCCESS - The function completes successfully
3502
3503 --*/
3504 {
3505 FILE *Fp;
3506
3507 Fp = fopen (FileName, "w+t");
3508 if (Fp == NULL) {
3509 printf ("Error in opening file %s\n", FileName);
3510 return EFI_ABORTED;
3511 }
3512
3513 while (BsfInfo != NULL) {
3514 if (strlen (BsfInfo->CompName) != 0) {
3515 fprintf (Fp, "\n%s\n", BsfInfo->CompName);
3516 } else {
3517 fprintf (Fp, "\n%s\n", "Name not available");
3518 }
3519
3520 fprintf (Fp, "%d\n", BsfInfo->CompPreferredAddress);
3521 fprintf (Fp, "%d\n", BsfInfo->CompSize);
3522 fprintf (Fp, "%d\n", BsfInfo->Align);
3523
3524 BsfInfo = BsfInfo->NextBsfInfo;
3525 }
3526
3527 if (Fp) {
3528 fclose (Fp);
3529 }
3530
3531 return EFI_SUCCESS;
3532 }