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