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