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