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