Added or modified utility version and usage display.
[people/mcb30/edk2.git] / edk2 / Tools / CCode / Source / GenBsfImage / GenBsfImage.c
1 /*++\r
2 \r
3 Copyright (c)  1999 - 2006, Intel Corporation. All rights reserved\r
4 This software and associated documentation (if any) is furnished\r
5 under a license and may only be used or copied in accordance\r
6 with the terms of the license. Except as permitted by such\r
7 license, no part of this software or documentation may be\r
8 reproduced, stored in a retrieval system, or transmitted in any\r
9 form or by any means without the express written consent of\r
10 Intel Corporation.\r
11 \r
12 \r
13 Module Name:\r
14 \r
15   GenBsfImage.c\r
16 \r
17 Abstract:\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
36 EFI_GUID      Bsf1NameGuid = EFI_IPF_VTF1_GUID\r
37 EFI_GUID      Bsf2NameGuid = EFI_IPF_VTF2_GUID\r
38 \r
39 CHAR8           **TokenStr;\r
40 CHAR8           **OrgStrTokPtr;\r
41 \r
42 PARSED_BSF_INFO *FileListPtr;\r
43 PARSED_BSF_INFO *FileListHeadPtr;\r
44 \r
45 VOID            *Bsf1Buffer;\r
46 VOID            *Bsf1EndBuffer;\r
47 VOID            *Bsf2Buffer;\r
48 VOID            *Bsf2EndBuffer;\r
49 \r
50 UINTN           ValidLineNum        = 0;\r
51 UINTN           ValidFFDFileListNum = 0;\r
52 \r
53 //\r
54 // Section Description and their number of occurences in *.INF file\r
55 //\r
56 UINTN           NumFvFiles        = 0;\r
57 UINTN           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
63 BOOLEAN         BSFPresent = FALSE;\r
64 \r
65 //\r
66 // Address related information\r
67 //\r
68 UINT64          Fv1BaseAddress        = 0;\r
69 UINT64          Fv2BaseAddress        = 0;\r
70 UINT64          Fv1EndAddress         = 0;\r
71 UINT64          Fv2EndAddress         = 0;\r
72 UINT32          Bsf1TotalSize         = SIZE_TO_OFFSET_PAL_A_END;\r
73 UINT64          Bsf1LastStartAddress  = 0;\r
74 UINT32          Bsf2TotalSize         = 0;\r
75 UINT64          Bsf2LastStartAddress  = 0;\r
76 \r
77 UINT32          BufferToTop           = 0;\r
78 \r
79 //\r
80 // IA32 Reset Vector Bin name\r
81 //\r
82 CHAR8           IA32BinFile[FILE_NAME_SIZE];\r
83 \r
84 //\r
85 // Function Implementations\r
86 //\r
87 VOID\r
88 BuildTokenList (\r
89   IN  CHAR8 *Token\r
90   )\r
91 /*++\r
92 Routine Description:\r
93 \r
94   This function builds the token list in an array which will be parsed later\r
95 \r
96 Arguments:\r
97 \r
98   Token    - The pointer of string\r
99 \r
100 Returns:\r
101 \r
102   None\r
103 \r
104 --*/\r
105 {\r
106   strcpy (*TokenStr, Token);\r
107   TokenStr++;\r
108 }\r
109 \r
110 EFI_STATUS\r
111 ConvertVersionInfo (\r
112   IN      CHAR8     *Str,\r
113   IN OUT  UINT8     *MajorVer,\r
114   IN OUT  UINT8     *MinorVer\r
115   )\r
116 /*++\r
117 Routine Description:\r
118 \r
119   This function converts GUID string to GUID\r
120 \r
121 Arguments:\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
127 Returns:\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
162 VOID\r
163 TrimLine (\r
164   IN  CHAR8 *Line\r
165   )\r
166 /*++\r
167 Routine Description:\r
168 \r
169   This function cleans up the line by removing all whitespace and \r
170   comments\r
171 \r
172 Arguments:\r
173 \r
174   Line   - The pointer of the string\r
175 \r
176 Returns:\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
212 VOID\r
213 ValidLineCount (\r
214   IN  FILE *Fp\r
215   )\r
216 /*++\r
217 \r
218 Routine Description:\r
219 \r
220   This function calculated number of valid lines in a input file.\r
221   \r
222 Arguments:\r
223 \r
224   Fp    - Pointer to a file handle which has been opened.\r
225 \r
226 Returns:\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
244 VOID\r
245 ParseInputFile (\r
246   IN  FILE *Fp\r
247   )\r
248 /*++\r
249   \r
250 Routine Description:\r
251 \r
252   This function parses the input file and tokenize the string\r
253   \r
254 Arguments:\r
255 \r
256   Fp    - Pointer to a file handle which has been opened.\r
257   \r
258 Returns:\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
287 EFI_STATUS\r
288 InitializeComps (\r
289   VOID\r
290   )\r
291 /*++\r
292 \r
293 Routine 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
299 Arguments:\r
300 \r
301   None\r
302 \r
303 Returns:\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
325 VOID\r
326 ParseAndUpdateComponents (\r
327   IN  PARSED_BSF_INFO   *BsfInfo\r
328   )\r
329 /*++\r
330 \r
331 Routine 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
336 Arguments:\r
337 \r
338   BsfInfo  - A pointer to the BSF Info Structure\r
339   \r
340 \r
341 Returns:\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
418 VOID\r
419 InitializeInFileInfo (\r
420   VOID\r
421   )\r
422 /*++\r
423 \r
424 Routine 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
429 Arguments:\r
430 \r
431   NONE\r
432 \r
433 Returns:\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
495 EFI_STATUS\r
496 GetBsfRelatedInfoFromInfFile (\r
497   IN  CHAR8 *FileName\r
498   )\r
499 /*++\r
500   \r
501 Routine 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
506 Arguments:\r
507 \r
508   FileName  - FileName which needed to be read to parse data\r
509 \r
510 Returns:\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
579 VOID\r
580 GetRelativeAddressInBsfBuffer (\r
581   IN      UINT64     Address,\r
582   IN OUT  UINTN      *RelativeAddress,\r
583   IN      LOC_TYPE   LocType\r
584   )\r
585 /*++\r
586   \r
587 Routine 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
594 Arguments:\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
601 Returns:\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
620 EFI_STATUS\r
621 GetComponentVersionInfo (\r
622   IN  OUT PARSED_BSF_INFO   *BsfInfo,\r
623   IN      UINT8             *Buffer\r
624   )\r
625 /*++\r
626 Routine Description:\r
627 \r
628   This function will extract the version information from File\r
629   \r
630 Arguments:\r
631 \r
632   BsfInfo  - A Pointer to the BSF Info Structure\r
633   Buffer   - A Pointer to type UINT8 \r
634 \r
635 Returns:\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
663 BOOLEAN\r
664 CheckAddressAlignment (\r
665   IN      UINT64  Address,\r
666   IN      UINT64  AlignmentData,\r
667   IN OUT  UINT64  *AlignAdjustByte\r
668   )\r
669 /*++\r
670   \r
671 Routine 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
678 Arguments:\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
684 Returns:\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
706 EFI_STATUS\r
707 GetFitTableStartAddress (\r
708   IN OUT  FIT_TABLE   **FitTable\r
709   )\r
710 /*++\r
711   \r
712 Routine Description:\r
713 \r
714   Get the FIT table start address in BSF Buffer\r
715   \r
716 Arguments:\r
717 \r
718   FitTable    - Pointer to available fit table where new component can be added\r
719   \r
720 Returns:\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
755 EFI_STATUS\r
756 GetNextAvailableFitPtr (\r
757   IN  FIT_TABLE   **FitPtr\r
758   )\r
759 /*++\r
760   \r
761 Routine 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
770 Arguments:\r
771 \r
772   FitPtr    - Pointer to available fit table where new component can be added\r
773   \r
774 Returns:\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
822 INTN\r
823 CompareItems (\r
824   IN const VOID  *Arg1,\r
825   IN const VOID  *Arg2\r
826   )\r
827 /*++\r
828 \r
829 Routine 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
834 Arguments:\r
835     \r
836     Arg1  -   Pointer to Arg1\r
837     Arg2  -   Pointer to Arg2\r
838     \r
839 Returns:\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
854 VOID\r
855 SortFitTable (\r
856   IN  VOID\r
857   )\r
858 /*++\r
859 \r
860 Routine 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
865 Arguments:\r
866     \r
867     VOID\r
868 \r
869 Returns:\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
894 VOID\r
895 UpdateFitEntryForFwVolume (\r
896   IN  UINT64  Size\r
897   )\r
898 /*++\r
899   \r
900 Routine 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
908 Arguments:\r
909 \r
910   Size   - Firmware Volume Size\r
911   \r
912 Returns:\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
966 EFI_STATUS\r
967 UpdateFitEntryForNonBSFComp (\r
968   IN  PARSED_BSF_INFO   *BsfInfo\r
969   )\r
970 /*++\r
971   \r
972 Routine 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
979 Arguments:\r
980 \r
981   BsfInfo    - Pointer to BSF Info Structure\r
982   \r
983 Returns:\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
1040 EFI_STATUS\r
1041 UpdateEntryPoint (\r
1042   IN  PARSED_BSF_INFO   *BsfInfo,\r
1043   IN  UINT64            *CompStartAddress\r
1044   )\r
1045 /*++\r
1046   \r
1047 Routine Description:\r
1048 \r
1049   This function updated the architectural entry point in IPF, SALE_ENTRY.\r
1050   \r
1051 Arguments:\r
1052 \r
1053   BsfInfo            - Pointer to BSF Info Structure \r
1054   CompStartAddress   - Pointer to Component Start Address\r
1055   \r
1056 Returns:\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
1113 EFI_STATUS\r
1114 CreateAndUpdateComponent (\r
1115   IN  PARSED_BSF_INFO   *BsfInfo\r
1116   )\r
1117 /*++\r
1118   \r
1119 Routine 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
1125 Arguments:\r
1126 \r
1127   BsfInfo    - Pointer to Parsed Info\r
1128   \r
1129 Returns:\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
1291 EFI_STATUS\r
1292 CreateAndUpdatePAL_A (\r
1293   IN  PARSED_BSF_INFO   *BsfInfo\r
1294   )\r
1295 /*++\r
1296   \r
1297 Routine 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
1302 Arguments:\r
1303 \r
1304   BsfInfo    - Pointer to Parsed Info\r
1305   \r
1306 Returns:\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
1409 EFI_STATUS\r
1410 CreateFitTableAndInitialize (\r
1411   IN  PARSED_BSF_INFO   *BsfInfo\r
1412   )\r
1413 /*++\r
1414   \r
1415 Routine 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
1420 Arguments:\r
1421 \r
1422   BsfInfo    - Pointer to Parsed Info\r
1423   \r
1424 Returns:\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
1499 EFI_STATUS\r
1500 WriteBsfBinary (\r
1501   IN CHAR8     *FileName,\r
1502   IN UINT32    BsfSize,\r
1503   IN LOC_TYPE  LocType\r
1504   )\r
1505 /*++\r
1506 \r
1507 Routine Description:\r
1508 \r
1509   Write Firmware Volume from memory to a file.\r
1510   \r
1511 Arguments:\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
1517 Returns:\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
1559 EFI_STATUS\r
1560 UpdateBsfBuffer (\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
1568 Routine Description:\r
1569 \r
1570   Update the Firmware Volume Buffer with requested buffer data\r
1571   \r
1572 Arguments:\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
1581 Returns:\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
1612 EFI_STATUS\r
1613 UpdateFfsHeader (\r
1614   IN UINT32         TotalBsfSize,\r
1615   IN LOC_TYPE       LocType  \r
1616   )\r
1617 /*++\r
1618 \r
1619 Routine Description:\r
1620 \r
1621   Update the Firmware Volume Buffer with requested buffer data\r
1622   \r
1623 Arguments:\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
1629 Returns:\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
1683 EFI_STATUS\r
1684 ValidateAddressAndSize (\r
1685   IN  UINT64  BaseAddress,\r
1686   IN  UINT64  FwVolSize\r
1687   )\r
1688 /*++\r
1689 \r
1690 Routine Description:\r
1691 \r
1692   Update the Firmware Volume Buffer with requested buffer data\r
1693   \r
1694 Arguments:\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
1700 Returns:\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
1714 EFI_STATUS\r
1715 UpdateIA32ResetVector (\r
1716   IN  CHAR8   *FileName,\r
1717   IN  UINT64  FirstFwVSize\r
1718   )\r
1719 /*++\r
1720 \r
1721 Routine Description:\r
1722 \r
1723   Update the 16 byte IA32 Reset vector to maintain the compatibility\r
1724   \r
1725 Arguments:\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
1730 Returns:\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
1778 VOID\r
1779 CleanUpMemory (\r
1780   VOID\r
1781   )\r
1782 /*++\r
1783 \r
1784 Routine Description:\r
1785 \r
1786   This function cleans up any allocated buffer\r
1787   \r
1788 Arguments:\r
1789 \r
1790   NONE\r
1791 \r
1792 Returns:\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
1819 EFI_STATUS\r
1820 ProcessAndCreateBsf (\r
1821   IN  UINT64  Size\r
1822   )\r
1823 /*++\r
1824 \r
1825 Routine 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
1830 Arguments:\r
1831 \r
1832   Size   - Size of the Firmware Volume of which, this BSF belongs to.\r
1833 \r
1834 Returns:\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
1903 EFI_STATUS\r
1904 GenerateBsfImage (\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
1912 Routine Description:\r
1913 \r
1914   This is the main function which will be called from application.\r
1915 \r
1916 Arguments:\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
1923 Returns:\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
2083 EFI_STATUS\r
2084 PeimFixupInFitTable (\r
2085   IN  UINT64  StartAddress\r
2086   )\r
2087 /*++\r
2088 \r
2089 Routine Description:\r
2090 \r
2091   This function is an entry point to fixup SAL-E entry point.\r
2092 \r
2093 Arguments:\r
2094 \r
2095   StartAddress - StartAddress for PEIM.....\r
2096     \r
2097 Returns:\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
2165 EFI_STATUS\r
2166 UpdateSymFile (\r
2167   IN UINT64 BaseAddress,\r
2168   IN CHAR8  *DestFileName,\r
2169   IN CHAR8  *SourceFileName\r
2170   )\r
2171 /*++\r
2172 \r
2173 Routine 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
2178 Arguments:\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
2184 Returns:\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
2302 EFI_STATUS\r
2303 CalculateFitTableChecksum (\r
2304   VOID\r
2305   )\r
2306 /*++\r
2307   \r
2308 Routine 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
2314 Arguments:\r
2315 \r
2316   NONE\r
2317   \r
2318 Returns:\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
2359 VOID\r
2360 Version (\r
2361   VOID\r
2362   )\r
2363 /*++\r
2364 \r
2365 Routine Description:\r
2366 \r
2367   Displays the standard utility information to SDTOUT\r
2368 \r
2369 Arguments:\r
2370 \r
2371   None\r
2372 \r
2373 Returns:\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.\n",\r
2381     UTILITY_NAME,\r
2382     UTILITY_MAJOR_VERSION,\r
2383     UTILITY_MINOR_VERSION\r
2384     );\r
2385 }\r
2386 \r
2387 VOID\r
2388 Usage (\r
2389   VOID\r
2390   )\r
2391 /*++\r
2392 \r
2393 Routine Description:\r
2394 \r
2395   Displays the utility usage syntax to STDOUT\r
2396 \r
2397 Arguments:\r
2398 \r
2399   None\r
2400 \r
2401 Returns:\r
2402 \r
2403   None\r
2404 \r
2405 --*/\r
2406 {\r
2407   Version();\r
2408   \r
2409   printf (\r
2410     "\nUsage: %s -B BaseAddress -S FwVolumeSize\n",\r
2411     UTILITY_NAME\r
2412     );\r
2413   printf ("  Where:\n");\r
2414   printf ("     BaseAddress is the starting address of Firmware Volume where Boot\n");\r
2415   printf ("              Strapped Image will reside.\n");\r
2416   printf ("     FwVolumeSize is the size of Firmware Volume.\n");\r
2417 }\r
2418 \r
2419 EFI_STATUS\r
2420 main (\r
2421   IN UINTN  argc,\r
2422   IN  CHAR8 **argv\r
2423   )\r
2424 /*++\r
2425 \r
2426 Routine Description:\r
2427 \r
2428   This utility uses GenBsfImage.dll to build a Boot Strap File Image which will be\r
2429   part of firmware volume image.\r
2430 \r
2431 Arguments:\r
2432 \r
2433   argc   - The count of the parameters\r
2434   argv   - The parameters\r
2435 \r
2436 \r
2437 Returns:\r
2438 \r
2439   0   - No error conditions detected.\r
2440   1   - One or more of the input parameters is invalid.\r
2441   2   - A resource required by the utility was unavailable.  \r
2442       - Most commonly this will be memory allocation or file creation.\r
2443   3   - GenFvImage.dll could not be loaded.\r
2444   4   - Error executing the GenFvImage dll.\r
2445   5   - Now this tool does not support the IA32 platform\r
2446 \r
2447 --*/\r
2448 {\r
2449   UINT8       Index;\r
2450   UINT64      StartAddress1;\r
2451   UINT64      StartAddress2;\r
2452   UINT64      FwVolSize1;\r
2453   UINT64      FwVolSize2;\r
2454   BOOLEAN     FirstRoundB;\r
2455   BOOLEAN     FirstRoundS;\r
2456   EFI_STATUS  Status;\r
2457   BOOLEAN     IsIA32;\r
2458 \r
2459   //\r
2460   // Verify the correct number of IA32 arguments\r
2461   //\r
2462   IsIA32 = FALSE;\r
2463   if (argc == IA32_ARGS) {\r
2464     //\r
2465     //  Now this tool is not used for IA32 platform, if it will be used in future,\r
2466     //  the IA32-specific functions need to be updated and verified, the updating can  \r
2467     //  refer to IPF relevant functions)\r
2468     //\r
2469     printf ("ERROR: Now this tool does not support the IA32 platform!\n");\r
2470     printf ("ERROR: And the IA32-specific functions need to be updated and verified!\n");\r
2471     return 5;\r
2472     \r
2473     /*\r
2474     StartAddress1 = 0;\r
2475     IsIA32        = TRUE;\r
2476 \r
2477     //\r
2478     // Parse the command line arguments\r
2479     //\r
2480     for (Index = 1; Index < IA32_ARGS; Index += 2) {\r
2481 \r
2482       //\r
2483       // Make sure argument pair begin with - or /\r
2484       //\r
2485       if (argv[Index][0] != '-' && argv[Index][0] != '/') {\r
2486         Usage ();\r
2487         printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");\r
2488         return 1;\r
2489       }\r
2490 \r
2491       //\r
2492       // Make sure argument specifier is only one letter\r
2493       //\r
2494       if (argv[Index][2] != 0) {\r
2495         Usage ();\r
2496         printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);\r
2497         return 1;\r
2498       }\r
2499 \r
2500       //\r
2501       // Determine argument to read\r
2502       //\r
2503       switch (argv[Index][1]) {\r
2504 \r
2505       case 't':\r
2506       case 'T':\r
2507         Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);\r
2508         if (Status != EFI_SUCCESS) {\r
2509           printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);\r
2510           return 1;\r
2511         }\r
2512         break;\r
2513 \r
2514       default:\r
2515         Usage ();\r
2516         printf ("Unrecognized IA32 argument \"%s\".\n", argv[Index]);\r
2517         IsIA32 = FALSE;\r
2518         break;\r
2519       }\r
2520     }\r
2521 \r
2522     if (IsIA32) {\r
2523       //\r
2524       // Call the GenBsfImage \r
2525       //\r
2526       Status = Generate32BsfImage (StartAddress1);\r
2527 \r
2528       if (EFI_ERROR(Status)) {\r
2529         switch (Status) {\r
2530 \r
2531         case EFI_INVALID_PARAMETER:\r
2532           printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");\r
2533           break;\r
2534 \r
2535         case EFI_ABORTED:\r
2536           printf ("\nERROR: Error detected while creating the file image.\n");\r
2537           break;\r
2538 \r
2539         case EFI_OUT_OF_RESOURCES:\r
2540           printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");\r
2541           break;\r
2542 \r
2543         case EFI_VOLUME_CORRUPTED:\r
2544           printf ("\nERROR: No base address was specified \n");\r
2545           break;\r
2546 \r
2547         default:\r
2548           printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);\r
2549           break;\r
2550         }\r
2551         return 2;\r
2552       }\r
2553 \r
2554       return 0;\r
2555     }\r
2556     */\r
2557   } \r
2558 \r
2559   //\r
2560   // Verify the correct number of arguments\r
2561   //\r
2562   if (argc < 1) {\r
2563     Usage();\r
2564     return 1;\r
2565   }\r
2566   \r
2567   if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||\r
2568       (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {\r
2569     Usage();\r
2570     return 1;\r
2571   }\r
2572   \r
2573   if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {\r
2574     Version();\r
2575     return 1;\r
2576   }\r
2577  \r
2578   if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {\r
2579     Usage ();\r
2580     return 1;\r
2581   }\r
2582 \r
2583   //\r
2584   // Initialize variables\r
2585   //\r
2586   StartAddress1 = 0;\r
2587   StartAddress2 = 0;\r
2588   FwVolSize1    = 0;\r
2589   FwVolSize2    = 0;\r
2590   FirstRoundB   = TRUE;\r
2591   FirstRoundS   = TRUE;\r
2592 \r
2593   //\r
2594   // Parse the command line arguments\r
2595   //\r
2596   for (Index = 1; Index < argc; Index += 2) {\r
2597 \r
2598     //\r
2599     // Make sure argument pair begin with - or /\r
2600     //\r
2601     if (argv[Index][0] != '-' && argv[Index][0] != '/') {\r
2602       Usage ();\r
2603       printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");\r
2604       return 1;\r
2605     }\r
2606 \r
2607     //\r
2608     // Make sure argument specifier is only one letter\r
2609     //\r
2610     if (argv[Index][2] != 0) {\r
2611       Usage ();\r
2612       printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);\r
2613       return 1;\r
2614     }\r
2615 \r
2616     //\r
2617     // Determine argument to read\r
2618     //\r
2619     switch (argv[Index][1]) {\r
2620 \r
2621     case 'B':\r
2622     case 'b':\r
2623       if (FirstRoundB) {\r
2624         Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);\r
2625         FirstRoundB = FALSE;\r
2626       } else {\r
2627         Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);\r
2628       }\r
2629 \r
2630       if (Status != EFI_SUCCESS) {\r
2631         printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);\r
2632         return 1;\r
2633       }\r
2634       break;\r
2635 \r
2636     case 'S':\r
2637     case 's':\r
2638       if (FirstRoundS) {\r
2639         Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);\r
2640         FirstRoundS = FALSE;\r
2641       } else {\r
2642         Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);\r
2643       }\r
2644 \r
2645       if (Status != EFI_SUCCESS) {\r
2646         printf ("\nERROR: Bad size \"%s\"\n", argv[Index + 1]);\r
2647         return 1;\r
2648       }\r
2649       break;\r
2650 \r
2651     default:\r
2652       Usage ();\r
2653       printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);\r
2654       return 1;\r
2655       break;\r
2656     }\r
2657   }\r
2658 \r
2659   //\r
2660   // Call the GenBsfImage\r
2661   //\r
2662   Status = GenerateBsfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2);\r
2663 \r
2664   if (EFI_ERROR (Status)) {\r
2665     switch (Status) {\r
2666 \r
2667     case EFI_INVALID_PARAMETER:\r
2668       printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");\r
2669       break;\r
2670 \r
2671     case EFI_ABORTED:\r
2672       printf ("\nERROR: Error detected while creating the file image.\n");\r
2673       break;\r
2674 \r
2675     case EFI_OUT_OF_RESOURCES:\r
2676       printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");\r
2677       break;\r
2678 \r
2679     case EFI_VOLUME_CORRUPTED:\r
2680       printf ("\nERROR: No base address was specified \n");\r
2681       break;\r
2682 \r
2683     default:\r
2684       printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);\r
2685       break;\r
2686     }\r
2687     return 2;\r
2688   }\r
2689   return 0;\r
2690 }\r
2691 \r
2692 EFI_STATUS\r
2693 Generate32BsfImage (\r
2694 IN  UINT64  BootFileStartAddress\r
2695   )\r
2696 /*++\r
2697 \r
2698 Routine Description:\r
2699 \r
2700   This is the main IA32 function which will be called from application.\r
2701   (Now this tool is not used for IA32 platform, if it will be used in future,\r
2702   the relative functions need to be updated, the updating can refer to IPF \r
2703   functions)\r
2704 \r
2705 Arguments:\r
2706 \r
2707   BootFileStartAddress   - Top Address of Boot File\r
2708 \r
2709 Returns:\r
2710  \r
2711   The return value can be any of the values \r
2712   returned by the calls to following functions:\r
2713       Get32BsfRelatedInfoFromInfFile\r
2714       CreateBsfBuffer\r
2715       ProcessAndCreate32Bsf\r
2716       Update32FfsHeader\r
2717       WriteBsfBinary\r
2718   \r
2719 --*/\r
2720 {\r
2721   EFI_STATUS    Status;\r
2722   UINT32        BsfSize;\r
2723   CHAR8         OutFileName[FILE_NAME_SIZE];\r
2724 \r
2725   EFI_GUID      BsfNameGuid = EFI_IA32_BOOT_STRAP_GUID;\r
2726 \r
2727   Status = EFI_UNSUPPORTED;\r
2728 \r
2729   memset (OutFileName, 0, FILE_NAME_SIZE);\r
2730 \r
2731   sprintf (\r
2732     OutFileName, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",\r
2733     BsfNameGuid.Data1,\r
2734     BsfNameGuid.Data2,\r
2735     BsfNameGuid.Data3,\r
2736     BsfNameGuid.Data4[0],\r
2737     BsfNameGuid.Data4[1],\r
2738     BsfNameGuid.Data4[2],\r
2739     BsfNameGuid.Data4[3],\r
2740     BsfNameGuid.Data4[4],\r
2741     BsfNameGuid.Data4[5],\r
2742     BsfNameGuid.Data4[6],\r
2743     BsfNameGuid.Data4[7],\r
2744     BSF_OUTPUT_FILE\r
2745     );\r
2746 \r
2747 \r
2748   Status = Get32BsfRelatedInfoFromInfFile (BSF_INPUT_FILE);\r
2749 \r
2750   if (Status != EFI_SUCCESS) {\r
2751     printf ("\nERROR: Error in parsing input file");\r
2752     CleanUpMemory ();\r
2753     return Status;\r
2754   }\r
2755 \r
2756   if (GetTotal32BsfSize (&BsfSize) == EFI_SUCCESS) {\r
2757     Bsf1Buffer = malloc ((UINTN) BsfSize);\r
2758     if (Bsf1Buffer == NULL) {\r
2759       printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");\r
2760       CleanUpMemory ();\r
2761       return EFI_OUT_OF_RESOURCES;\r
2762     }\r
2763     memset (Bsf1Buffer, 0x00, (UINTN) BsfSize);\r
2764   } else {\r
2765     printf ("\nERROR: Could not get BSF size.");\r
2766     CleanUpMemory ();\r
2767     return EFI_ABORTED;\r
2768   }\r
2769 \r
2770   //\r
2771   //VTF must align properly\r
2772   //\r
2773   Bsf1LastStartAddress = BootFileStartAddress - BsfSize;\r
2774   Bsf1LastStartAddress = Bsf1LastStartAddress & -8;\r
2775   BsfSize          = (UINT32)BootFileStartAddress - (UINT32)Bsf1LastStartAddress;\r
2776   Bsf1LastStartAddress = BsfSize;\r
2777   BufferToTop      = (UINT32)BootFileStartAddress - BsfSize;\r
2778 \r
2779   Status = ProcessAndCreate32Bsf (BsfSize);\r
2780 \r
2781   if (Status != EFI_SUCCESS) {\r
2782     CleanUpMemory();\r
2783     return Status;\r
2784   }\r
2785 \r
2786   //\r
2787   // Write the FFS header\r
2788   //\r
2789   Status = Update32FfsHeader (BsfSize);\r
2790 \r
2791   if (Status != EFI_SUCCESS) {\r
2792     CleanUpMemory();\r
2793     return Status;\r
2794   }\r
2795 \r
2796   // \r
2797   // Calculate the Start address of this BSF\r
2798   //\r
2799   Bsf1Buffer = (UINT8 *)Bsf1Buffer + Bsf1LastStartAddress;\r
2800 \r
2801   //\r
2802   // Update the BSF buffer into specified BSF binary file\r
2803   //\r
2804   Status = WriteBsfBinary (OutFileName, BsfSize - (UINT32)Bsf1LastStartAddress, FIRST_VTF);\r
2805 \r
2806   if (Status != EFI_SUCCESS) {\r
2807     CleanUpMemory();\r
2808     return Status;\r
2809   }\r
2810 \r
2811   Status = Write32SoftFit (IA32_SOFT_FIT, FileListHeadPtr);\r
2812 \r
2813   if (Status != EFI_SUCCESS) {\r
2814     CleanUpMemory();\r
2815     return Status;\r
2816   }\r
2817   \r
2818   CleanUpMemory ();\r
2819   printf ("\n");  \r
2820 \r
2821   return Status;\r
2822 }\r
2823 \r
2824 EFI_STATUS\r
2825 GetTotal32BsfSize(\r
2826   IN  UINT32  *BsfSize \r
2827   )\r
2828 /*++\r
2829 \r
2830 Routine Description:\r
2831 \r
2832   This function calculates total size for IA32 BSF which would be needed to create\r
2833   the buffer. This will be done using Passed Info link list and looking for the\r
2834   size of the components which belong to BSF. The addtional file header is accounted.\r
2835 \r
2836 Arguments:\r
2837 \r
2838   BSFSize     - Pointer to the size of IA32 BSF \r
2839 \r
2840 Returns:\r
2841 \r
2842   EFI_ABORTED - Returned due to one of the following resons:\r
2843                 (a) Error Opening File\r
2844   EFI_SUCCESS - The fuction completes successfully\r
2845 \r
2846 --*/\r
2847 {\r
2848   PARSED_BSF_INFO     *BsfInfo;\r
2849   FILE                *Fp;\r
2850   UINT32              Alignment;\r
2851 \r
2852   *BsfSize = 0;\r
2853   Alignment = 0;\r
2854   \r
2855   BsfInfo = FileListHeadPtr;\r
2856 \r
2857   while (BsfInfo != NULL) {\r
2858     if (BsfInfo->LocationType != SECOND_VTF) {\r
2859 \r
2860       if ( BsfInfo->Align ) {\r
2861         //\r
2862         // Create additional align to compensate for component boundary requirements\r
2863         //\r
2864         Alignment = 1 << BsfInfo->Align;\r
2865         *BsfSize += Alignment;\r
2866       }\r
2867       \r
2868       if (BsfInfo->PreferredSize) {\r
2869         *BsfSize += BsfInfo->CompSize;\r
2870       } else {\r
2871         Fp = fopen (BsfInfo->CompBinName,"r+b");\r
2872 \r
2873         if (Fp == NULL) {\r
2874           printf ("\nERROR: Error in opening file %s", BsfInfo->CompBinName);\r
2875           return EFI_ABORTED;\r
2876         }\r
2877         \r
2878         *BsfSize += _filelength (fileno (Fp));\r
2879         \r
2880         if (Fp) {\r
2881           fclose (Fp);\r
2882         }\r
2883       }    \r
2884     }\r
2885     BsfInfo = BsfInfo->NextBsfInfo;\r
2886   }\r
2887 \r
2888   //\r
2889   // Add file header space\r
2890   //\r
2891   *BsfSize += sizeof (EFI_FFS_FILE_HEADER);\r
2892 \r
2893   //\r
2894   // Create additional to IA32 Seccore section header\r
2895   //\r
2896   *BsfSize += sizeof (EFI_COMMON_SECTION_HEADER);\r
2897 \r
2898   return EFI_SUCCESS;\r
2899 }\r
2900 \r
2901 EFI_STATUS\r
2902 ProcessAndCreate32Bsf (\r
2903   IN  UINT64  Size\r
2904   )\r
2905 /*++\r
2906 \r
2907 Routine Description:\r
2908 \r
2909   This function process the link list created during INF file parsing\r
2910   and create component in IA32 BSF\r
2911   \r
2912 Arguments:\r
2913 \r
2914   Size   - Size of the Firmware Volume of which, this BSF belongs to.\r
2915 \r
2916 Returns:\r
2917   \r
2918   EFI_UNSUPPORTED - Unknown component type\r
2919   EFI_SUCCESS     - The function completed successfully                 \r
2920 \r
2921 --*/\r
2922 {\r
2923   EFI_STATUS          Status;\r
2924   PARSED_BSF_INFO     *ParsedInfoPtr;\r
2925 \r
2926   Status = EFI_SUCCESS;\r
2927 \r
2928   ParsedInfoPtr = FileListHeadPtr;\r
2929 \r
2930   while (ParsedInfoPtr != NULL) {\r
2931     \r
2932     switch (ParsedInfoPtr->CompType) {\r
2933 \r
2934     case COMP_TYPE_SECCORE:\r
2935       Status = CreateAndUpdateSeccore (ParsedInfoPtr);\r
2936       break;\r
2937 \r
2938     default:\r
2939       //\r
2940       // Any other component type should be handled here. This will create the\r
2941       // image in specified BSF\r
2942       //\r
2943       Status = CreateAndUpdate32Component (ParsedInfoPtr);\r
2944       if (EFI_ERROR(Status)) {\r
2945         printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);\r
2946       }\r
2947       break;\r
2948     }\r
2949 \r
2950     ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;\r
2951   }\r
2952 \r
2953   return Status;\r
2954 }\r
2955 \r
2956 EFI_STATUS\r
2957 CreateAndUpdateSeccore (\r
2958   IN  PARSED_BSF_INFO   *BsfInfo\r
2959   )\r
2960 /*++\r
2961   \r
2962 Routine Description:\r
2963 \r
2964   This function reads the binary file for seccore and update them\r
2965   in IA32 BSF Buffer\r
2966   \r
2967 Arguments:\r
2968 \r
2969   BsfInfo    - Pointer to Parsed Info\r
2970   \r
2971 Returns:\r
2972 \r
2973   EFI_ABORTED           - Due to one of the following reasons:\r
2974                            (a)Error Opening File\r
2975                            (b)The PAL_A Size is more than specified size status\r
2976                               One of the values mentioned below returned from \r
2977                               call to UpdateSymFile\r
2978   EFI_SUCCESS           - The function completed successfully.\r
2979   EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
2980   EFI_ABORTED           - An error occurred.UpdateSymFile\r
2981   EFI_OUT_OF_RESOURCES  - Memory allocation failed.\r
2982    \r
2983 --*/\r
2984 {\r
2985   UINT8                      *SecbinStartAddress;\r
2986   UINT8                      *SecfileStartAddress;\r
2987   UINT32                     FileSize;\r
2988   UINT64                     NumByteRead;\r
2989   UINT8                      *Buffer;\r
2990   FILE                       *Fp;\r
2991   UINT64                     TotalLength;\r
2992   EFI_COMMON_SECTION_HEADER  *SecHeader;\r
2993 \r
2994   Fp = fopen (BsfInfo->CompBinName, "r+b");\r
2995 \r
2996   if (Fp == NULL) {\r
2997     printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);\r
2998     return EFI_ABORTED;\r
2999   }\r
3000 \r
3001   FileSize = _filelength (fileno (Fp));\r
3002 \r
3003   if (BsfInfo->PreferredSize) {\r
3004     if (FileSize > BsfInfo->CompSize) {\r
3005       printf("\nERROR: The Seccore Size is more than specified size");\r
3006       return EFI_ABORTED;\r
3007     }\r
3008 \r
3009     FileSize = BsfInfo->CompSize;\r
3010   }\r
3011 \r
3012   BsfInfo->CompSize = FileSize;\r
3013 \r
3014   Buffer = malloc ((UINTN) FileSize);\r
3015   if (Buffer == NULL) {\r
3016     return EFI_OUT_OF_RESOURCES;\r
3017   }\r
3018   memset (Buffer, 0, (UINTN) FileSize);\r
3019 \r
3020   //\r
3021   // Read seccore in a buffer\r
3022   //\r
3023   NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
3024   fclose (Fp);\r
3025 \r
3026   SecfileStartAddress = (UINT8 *) Bsf1Buffer + Bsf1LastStartAddress - FileSize - sizeof (EFI_COMMON_SECTION_HEADER); \r
3027   if (SecfileStartAddress == NULL) {\r
3028     return EFI_INVALID_PARAMETER;\r
3029   }\r
3030 \r
3031   SecbinStartAddress = SecfileStartAddress + sizeof (EFI_COMMON_SECTION_HEADER);\r
3032 \r
3033   BsfInfo->CompPreferredAddress = Bsf1LastStartAddress - FileSize + BufferToTop;\r
3034 \r
3035   //\r
3036   // write section header\r
3037   //\r
3038   memset (SecfileStartAddress, 0, sizeof (EFI_COMMON_SECTION_HEADER));\r
3039   SecHeader = (EFI_COMMON_SECTION_HEADER *) SecfileStartAddress;\r
3040   SecHeader->Type = EFI_SECTION_RAW;\r
3041   TotalLength     = sizeof (EFI_COMMON_SECTION_HEADER) + (UINT64) FileSize;\r
3042   memcpy (SecHeader->Size, &TotalLength, 3);\r
3043 \r
3044   //\r
3045   // write seccore\r
3046   //\r
3047   memcpy (SecbinStartAddress, Buffer, (UINTN) FileSize);\r
3048 \r
3049   if (Buffer) {\r
3050     free (Buffer);\r
3051   }\r
3052 \r
3053   Bsf1LastStartAddress = SecfileStartAddress - (UINT8 *) Bsf1Buffer;\r
3054 \r
3055   return EFI_SUCCESS;\r
3056 }\r
3057 \r
3058 EFI_STATUS\r
3059 CreateAndUpdate32Component (\r
3060   IN  PARSED_BSF_INFO   *BsfInfo\r
3061   )\r
3062 /*++\r
3063   \r
3064 Routine Description:\r
3065 \r
3066   This function reads the binary file for each components. Add it at aligned address.\r
3067   \r
3068 Arguments:\r
3069 \r
3070   BsfInfo    - Pointer to Parsed Info\r
3071   \r
3072 Returns:\r
3073 \r
3074   EFI_SUCCESS              - The function completed successful\r
3075   EFI_ABORTED              - Aborted due to one of the many reasons like:\r
3076                               (a) Component Size greater than the specified size.\r
3077                               (b) Error opening files.\r
3078   EFI_INVALID_PARAMETER    - Value returned from call to UpdateEntryPoint()\r
3079   EFI_OUT_OF_RESOURCES     - Memory allocation failed.\r
3080   \r
3081 --*/\r
3082 {\r
3083   UINT64      CompStartAddress;\r
3084   UINT32      FileSize;\r
3085   UINT64      NumByteRead;\r
3086   UINT8       *Buffer;\r
3087   FILE        *Fp;\r
3088   UINT8       *LocalBufferPtrToWrite;\r
3089   UINT64      Alignment;\r
3090 \r
3091   Fp = fopen (BsfInfo->CompBinName, "r+b");\r
3092 \r
3093   if (Fp == NULL) {\r
3094     printf("\nERROR: Opening file %s", BsfInfo->CompBinName);\r
3095     return EFI_ABORTED;\r
3096   }\r
3097 \r
3098   FileSize = _filelength (fileno (Fp));\r
3099 \r
3100   if (BsfInfo->PreferredSize) {\r
3101     if (FileSize > BsfInfo->CompSize) {\r
3102       printf("\nERROR: The component size is more than specified size");\r
3103       return EFI_ABORTED;\r
3104     }\r
3105     FileSize = BsfInfo->CompSize;\r
3106   }\r
3107   BsfInfo->CompSize = FileSize;\r
3108 \r
3109   Buffer = malloc ((UINTN) FileSize);\r
3110   if (Buffer == NULL) {\r
3111     return EFI_OUT_OF_RESOURCES;\r
3112   }\r
3113   memset (Buffer,0, (UINTN) FileSize);\r
3114 \r
3115   NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
3116   fclose (Fp);\r
3117 \r
3118   CompStartAddress = Bsf1LastStartAddress - FileSize + BufferToTop;\r
3119 \r
3120   if (BsfInfo->Align) {\r
3121     //\r
3122     // Create additional align to compensate for component boundary requirements\r
3123     //\r
3124     Alignment = 0 - (1 << BsfInfo->Align);\r
3125     CompStartAddress = CompStartAddress & Alignment;    \r
3126   }\r
3127 \r
3128   BsfInfo->CompPreferredAddress = CompStartAddress;\r
3129 \r
3130   //\r
3131   // write bin\r
3132   //\r
3133   LocalBufferPtrToWrite = (UINT8 *) Bsf1Buffer;\r
3134   Bsf1LastStartAddress  = CompStartAddress - BufferToTop;\r
3135   LocalBufferPtrToWrite += Bsf1LastStartAddress;\r
3136   memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) FileSize);  \r
3137   Bsf1LastStartAddress = CompStartAddress - BufferToTop;\r
3138 \r
3139   //\r
3140   // Free the buffer\r
3141   //\r
3142   if (Buffer) {\r
3143     free (Buffer);\r
3144   }\r
3145 \r
3146   return EFI_SUCCESS;\r
3147 }\r
3148 \r
3149 EFI_STATUS\r
3150 Update32FfsHeader(\r
3151   IN UINT32     BsfSize\r
3152   )\r
3153 /*++\r
3154 \r
3155 Routine Description:\r
3156 \r
3157   Update the Firmware Volume Buffer with requested buffer data\r
3158 \r
3159 Arguments:\r
3160 \r
3161   BsfSize     - Size of the IA32 BSF\r
3162 \r
3163 Returns:\r
3164   \r
3165   EFI_SUCCESS            - The function completed successfully\r
3166   EFI_INVALID_PARAMETER  - The Ffs File Header Pointer is NULL\r
3167 \r
3168 --*/\r
3169 {\r
3170   EFI_FFS_FILE_HEADER     *FileHeader;\r
3171   UINT32                  TotalBsfSize;\r
3172   EFI_GUID                EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
3173 \r
3174   \r
3175   //\r
3176   // Find the BSF file header location, the bsf file must be 8 bytes aligned\r
3177   //\r
3178   Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);\r
3179   Bsf1LastStartAddress += BufferToTop;\r
3180   Bsf1LastStartAddress = Bsf1LastStartAddress & -8;\r
3181   Bsf1LastStartAddress -= BufferToTop;\r
3182   FileHeader = (EFI_FFS_FILE_HEADER*)((UINT8*)Bsf1Buffer + Bsf1LastStartAddress);\r
3183 \r
3184   if (FileHeader == NULL) {\r
3185     return EFI_INVALID_PARAMETER;\r
3186   }\r
3187 \r
3188   //\r
3189   // write header\r
3190   //\r
3191   memset (FileHeader, 0, sizeof(EFI_FFS_FILE_HEADER));\r
3192   memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));\r
3193 \r
3194   FileHeader->Type = EFI_FV_FILETYPE_FREEFORM;\r
3195   FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;\r
3196 \r
3197   //\r
3198   // Now FileSize includes the EFI_FFS_FILE_HEADER\r
3199   //\r
3200   TotalBsfSize = BsfSize - (UINT32)Bsf1LastStartAddress;\r
3201   FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);\r
3202   FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);\r
3203   FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 0x00FF0000) >> 16);\r
3204 \r
3205   //\r
3206   // Fill in checksums and state, all three must be zero for the checksums.\r
3207   //\r
3208   FileHeader->IntegrityCheck.Checksum.Header = 0;\r
3209   FileHeader->IntegrityCheck.Checksum.File = 0;\r
3210   FileHeader->State = 0;\r
3211   FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8*) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
3212   FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8*) FileHeader, TotalBsfSize);\r
3213   FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
3214 \r
3215   return EFI_SUCCESS;\r
3216 }\r
3217 \r
3218 EFI_STATUS\r
3219 Get32BsfRelatedInfoFromInfFile (\r
3220   IN  CHAR8 *FileName\r
3221   )\r
3222 /*++\r
3223   \r
3224 Routine Description:\r
3225 \r
3226   This function reads the input file, parse it and create a list of tokens\r
3227   which is parsed and used, to intialize the data related to IA32 BSF\r
3228   \r
3229 Arguments:\r
3230 \r
3231   FileName  FileName which needed to be read to parse data\r
3232 \r
3233 Returns:\r
3234    \r
3235   EFI_ABORTED            Error in opening file\r
3236   EFI_INVALID_PARAMETER  File doesn't contain any valid informations\r
3237   EFI_OUT_OF_RESOURCES   Malloc Failed\r
3238   EFI_SUCCESS            The function completed successfully \r
3239 \r
3240 --*/\r
3241 {\r
3242   FILE          *Fp;\r
3243   UINTN         Index;\r
3244   EFI_STATUS    Status;\r
3245   \r
3246   Fp = fopen (FileName, "r");\r
3247   if (Fp == NULL) {\r
3248     printf ("\nERROR: Error in opening %s file\n", FileName);\r
3249     return EFI_ABORTED;\r
3250   }\r
3251   \r
3252   ValidLineCount (Fp);\r
3253   \r
3254   if (ValidLineNum == 0) {\r
3255     printf ("\nERROR: File doesn't contain any valid informations");\r
3256     return EFI_INVALID_PARAMETER;\r
3257   }\r
3258   \r
3259   TokenStr = (CHAR8 **)malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));\r
3260 \r
3261   if (TokenStr == NULL) {\r
3262     return EFI_OUT_OF_RESOURCES;\r
3263   }\r
3264   memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));\r
3265   OrgStrTokPtr = TokenStr;\r
3266   \r
3267   for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
3268     *TokenStr = (CHAR8 *)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
3269 \r
3270     if (*TokenStr == NULL) {\r
3271       free (OrgStrTokPtr);\r
3272       return EFI_OUT_OF_RESOURCES;\r
3273     }\r
3274     \r
3275     memset (*TokenStr, 0, FILE_NAME_SIZE);\r
3276 //    free (*TokenStr);\r
3277     TokenStr++;\r
3278   }\r
3279   \r
3280   TokenStr = NULL;\r
3281   TokenStr = OrgStrTokPtr;\r
3282   fseek (Fp, 0L, SEEK_SET);\r
3283   \r
3284   Status = InitializeComps();\r
3285 \r
3286   if (Status != EFI_SUCCESS) {\r
3287     free (TokenStr);\r
3288     return Status;\r
3289   }\r
3290   ParseInputFile (Fp);\r
3291   Initialize32InFileInfo ();\r
3292   \r
3293   if (Fp) {\r
3294     fclose (Fp);\r
3295   }\r
3296   free (TokenStr);\r
3297   return EFI_SUCCESS;\r
3298 }\r
3299 \r
3300 VOID\r
3301 Initialize32InFileInfo (\r
3302   VOID                     \r
3303   )\r
3304 /*++\r
3305 \r
3306 Routine Description:\r
3307 \r
3308   This function intializes the relevant global variable which is being\r
3309   used to store the information retrieved from IA32 INF file.\r
3310 \r
3311 Arguments:\r
3312 \r
3313   NONE\r
3314 \r
3315 Returns:\r
3316 \r
3317   NONE\r
3318 \r
3319 --*/\r
3320 {\r
3321   UINTN   SectionOptionFlag;\r
3322   UINTN   SectionCompFlag;\r
3323 \r
3324   SectionOptionFlag =0 ;\r
3325   SectionCompFlag = 0;  \r
3326   TokenStr = OrgStrTokPtr;\r
3327   while (*TokenStr != NULL) {\r
3328     if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {\r
3329       SectionOptionFlag = 1;\r
3330       SectionCompFlag = 0;\r
3331     }\r
3332     \r
3333     if (_stricmp (*TokenStr, "[COMPONENTS]") == 0) {\r
3334       if (FileListPtr == NULL) {\r
3335         FileListPtr = FileListHeadPtr;\r
3336       }\r
3337       \r
3338       SectionCompFlag = 1;\r
3339       SectionOptionFlag = 0;\r
3340       TokenStr++;\r
3341     }\r
3342     \r
3343     if (SectionOptionFlag) {\r
3344       if (_stricmp (*TokenStr, "IA32_RST_BIN") == 0) {\r
3345         *TokenStr++;\r
3346         strcpy (IA32BinFile, *TokenStr);\r
3347       }\r
3348     }\r
3349     \r
3350     if (SectionCompFlag) {\r
3351       if (_stricmp (*TokenStr, "COMP_NAME") == 0) {\r
3352         TokenStr++;\r
3353         strcpy (FileListPtr->CompName, *TokenStr);\r
3354         TokenStr++;\r
3355         ParseAndUpdate32Components (FileListPtr);\r
3356       }\r
3357       \r
3358       if (*TokenStr != NULL) {\r
3359         FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));\r
3360         if (FileListPtr->NextBsfInfo == NULL) {\r
3361           printf ("Error: Out of memory resources.\n");\r
3362           break;\r
3363         }\r
3364         FileListPtr = FileListPtr->NextBsfInfo;\r
3365         memset (FileListPtr, 0, sizeof(PARSED_BSF_INFO));\r
3366         FileListPtr->NextBsfInfo = NULL;\r
3367         continue;\r
3368       } else {\r
3369         break;\r
3370       }\r
3371     }\r
3372     \r
3373     TokenStr++;\r
3374   }\r
3375 }\r
3376 \r
3377 VOID \r
3378 ParseAndUpdate32Components (\r
3379   IN  PARSED_BSF_INFO   *BsfInfo\r
3380   )\r
3381 /*++\r
3382 \r
3383 Routine Description:\r
3384 \r
3385   This function intializes the relevant global variable which is being\r
3386   used to store the information retrieved from INF file.\r
3387   \r
3388 Arguments:\r
3389 \r
3390   BsfInfo   - A pointer to the BSF Info Structure\r
3391   \r
3392 \r
3393 Returns:\r
3394 \r
3395   None\r
3396 \r
3397 --*/\r
3398 {\r
3399   UINT64  StringValue;\r
3400   UINT64  AlignStringValue;\r
3401 \r
3402   while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {\r
3403 \r
3404     if (_stricmp (*TokenStr, "COMP_LOC") == 0) {\r
3405       TokenStr++;\r
3406       if (_stricmp (*TokenStr, "B") == 0) {\r
3407         BsfInfo->LocationType = FIRST_VTF;\r
3408       } else if (_stricmp (*TokenStr, "N") == 0) {\r
3409         BsfInfo->LocationType = SECOND_VTF;\r
3410       } else {\r
3411         BsfInfo->LocationType = NONE;\r
3412         printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);\r
3413       }\r
3414     } else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {\r
3415       TokenStr++;\r
3416       if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
3417         printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); \r
3418         return;\r
3419       }\r
3420       BsfInfo->CompType = (UINT8) StringValue;\r
3421     } else if (_stricmp (*TokenStr, "COMP_VER") == 0) {\r
3422       TokenStr++;\r
3423       if (_stricmp (*TokenStr, "-") == 0) {\r
3424         BsfInfo->VersionPresent = FALSE;\r
3425         BsfInfo->MajorVer = 0;\r
3426         BsfInfo->MinorVer = 0;\r
3427       } else {\r
3428         BsfInfo->VersionPresent = TRUE;\r
3429         ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);\r
3430       }\r
3431     } else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {\r
3432       TokenStr++;\r
3433       strcpy (BsfInfo->CompBinName, *TokenStr);\r
3434     } else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {\r
3435       TokenStr++;\r
3436       strcpy (BsfInfo->CompSymName, *TokenStr);\r
3437     } else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {\r
3438       TokenStr++;\r
3439       if (_stricmp (*TokenStr, "-") == 0) {\r
3440         BsfInfo->PreferredSize = FALSE;\r
3441         BsfInfo->CompSize = 0;\r
3442       } else {\r
3443         BsfInfo->PreferredSize = TRUE;\r
3444         if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
3445           printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); \r
3446           return;\r
3447         }\r
3448         BsfInfo->CompSize = (UINTN) StringValue;\r
3449       }\r
3450 \r
3451     } else if (_stricmp (*TokenStr, "COMP_CS") == 0) {\r
3452       TokenStr++;\r
3453       if (_stricmp (*TokenStr, "1") == 0) {\r
3454         BsfInfo->CheckSumRequired = 1;\r
3455       } else if (_stricmp (*TokenStr, "0") == 0) {\r
3456         BsfInfo->CheckSumRequired = 0;\r
3457       } else {\r
3458         printf ("\nERROR: Bad information in INF file about Checksum required field");\r
3459       }\r
3460     } else if (_stricmp (*TokenStr, "COMP_ALIGN") == 0) {\r
3461       TokenStr++;\r
3462       if (AsciiStringToUint64 (*TokenStr, FALSE, &AlignStringValue) != EFI_SUCCESS) {\r
3463         printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr); \r
3464         return;\r
3465       }\r
3466       if (AlignStringValue >= 0) {\r
3467         BsfInfo->Align = (UINT32) AlignStringValue;\r
3468       } else {\r
3469         printf ("\nERROR: invalid align \"%s\".", AlignStringValue); \r
3470         return;\r
3471       }\r
3472     }\r
3473     TokenStr++;\r
3474     if (*TokenStr == NULL) {\r
3475       break;\r
3476     }\r
3477   }\r
3478 }\r
3479 \r
3480 EFI_STATUS\r
3481 Write32SoftFit(\r
3482   IN CHAR8              *FileName,\r
3483   IN PARSED_BSF_INFO    *BsfInfo\r
3484   )\r
3485 /*++\r
3486 \r
3487 Routine Description:\r
3488 \r
3489   Write IA32 Firmware Volume component address from memory to a file.\r
3490   \r
3491 Arguments:\r
3492 \r
3493   FileName      Output File Name which needed to be created/\r
3494   BsfInfo       Parsed info link\r
3495   \r
3496 Returns:\r
3497 \r
3498   EFI_ABORTED  - Returned due to one of the following resons:\r
3499                   (a) Error Opening File\r
3500                   (b) Failing to copy buffers\r
3501   EFI_SUCCESS  - The function completes successfully\r
3502 \r
3503 --*/\r
3504 {\r
3505   FILE    *Fp;\r
3506 \r
3507   Fp = fopen (FileName, "w+t");\r
3508   if (Fp == NULL) {\r
3509     printf ("Error in opening file %s\n", FileName);\r
3510     return EFI_ABORTED;\r
3511   }\r
3512 \r