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