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