1 /**@file
2 This utility is part of build process for IA32/X64 FD.
3 It generates FIT table.
4 
5 Copyright (c) 2010-2020, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "FitGen.h"
11 
12 //
13 // FIT spec
14 //
15 #pragma pack (1)
16 typedef struct {
17   UINT64     Address;
18   UINT8      Size[3];
19   UINT8      Rsvd;
20   UINT16     Version;
21   UINT8      Type:7;
22   UINT8      C_V:1;
23   UINT8      Checksum;
24 } FIRMWARE_INTERFACE_TABLE_ENTRY;
25 
26 //
27 // Struct for policy
28 //
29 typedef struct {
30   UINT16     IndexPort;
31   UINT16     DataPort;
32   UINT8      Width;
33   UINT8      Bit;
34   UINT16     Index;
35   UINT8      Size[3];
36   UINT8      Rsvd;
37   UINT16     Version; // == 0
38   UINT8      Type:7;
39   UINT8      C_V:1;
40   UINT8      Checksum;
41 } FIRMWARE_INTERFACE_TABLE_ENTRY_PORT;
42 
43 #define FIT_ALIGNMENT          0x3F // 0xF is required previously, but if we need exclude FIT, we must set 64 bytes alignment.
44 #define BIOS_MODULE_ALIGNMENT  0x3F  // 64 bytes for AnC
45 #define MICROCODE_ALIGNMENT    0x7FF
46 
47 #define ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE          256
48 #define ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE          384
49 
50 #define ACM_HEADER_VERSION_3  (3 << 16)
51 #define ACM_MODULE_TYPE_CHIPSET_ACM                     2
52 #define ACM_MODULE_SUBTYPE_CAPABLE_OF_EXECUTE_AT_RESET  0x1
53 #define ACM_MODULE_SUBTYPE_ANC_MODULE                   0x2
54 #define ACM_MODULE_FLAG_PREPRODUCTION                   0x4000
55 #define ACM_MODULE_FLAG_DEBUG_SIGN                      0x8000
56 
57 
58 typedef struct {
59   UINT16     ModuleType;
60   UINT16     ModuleSubType;
61   UINT32     HeaderLen;
62   UINT32     HeaderVersion;
63   UINT16     ChipsetID;
64   UINT16     Flags;
65   UINT32     ModuleVendor;
66   UINT32     Date;
67   UINT32     Size;
68   UINT16     TxtSvn;
69   UINT16     SeSvn;
70   UINT32     CodeControl;
71   UINT32     ErrorEntryPoint;
72   UINT32     GDTLimit;
73   UINT32     GDTBasePtr;
74   UINT32     SegSel;
75   UINT32     EntryPoint;
76   UINT8      Rsvd2[64];
77   UINT32     KeySize; // 64
78   UINT32     ScratchSize; // 2 * KeySize + 15
79 //UINT8      RSAPubKey[64 * 4]; // KeySize * 4
80 //UINT32     RSAPubExp;
81 //UINT8      RSASig[256];
82   // End of AC module header
83 //UINT8      Scratch[(64 * 2 + 15) * 4]; // ScratchSize * 4
84   // User Area
85 //UINT8      UserArea[1];
86 } ACM_FORMAT;
87 
88 #define CHIPSET_ACM_INFORMATION_TABLE_VERSION_3  0x03
89 #define CHIPSET_ACM_INFORMATION_TABLE_VERSION_4  0x04
90 
91 #define CHIPSET_ACM_INFORMATION_TABLE_VERSION    CHIPSET_ACM_INFORMATION_TABLE_VERSION_3
92 
93 #define CHIPSET_ACM_INFORMATION_TABLE_GUID_V03 \
94   { 0x7FC03AAA, 0x18DB46A7, 0x8F69AC2E, 0x5A7F418D }
95 
96 #define CHIPSET_ACM_TYPE_BIOS   0
97 #define CHIPSET_ACM_TYPE_SINIT  1
98 
99 typedef struct {
100   UINT32    Guid0;
101   UINT32    Guid1;
102   UINT32    Guid2;
103   UINT32    Guid3;
104 } ACM_GUID;
105 
106 typedef struct {
107   ACM_GUID   Guid;
108   UINT8      ChipsetACMType;
109   UINT8      Version;
110   UINT16     Length;
111   UINT32     ChipsetIDList;
112   UINT32     OsSinitTableVer;
113   UINT32     MinMleHeaderVer;
114 //#if (CHIPSET_ACM_INFORMATION_TABLE_VERSION >= CHIPSET_ACM_INFORMATION_TABLE_VERSION_3)
115   UINT32     Capabilities;
116   UINT8      AcmVersion;
117   UINT8      AcmRevision[3];
118 //#if (CHIPSET_ACM_INFORMATION_TABLE_VERSION >= CHIPSET_ACM_INFORMATION_TABLE_VERSION_4)
119   UINT32     ProcessorIDList;
120 //#endif
121 //#endif
122 } CHIPSET_ACM_INFORMATION_TABLE;
123 
124 #define ACM_CHIPSET_ID_REVISION_ID_MAKE  0x1
125 
126 typedef struct {
127   UINT32     Flags;
128   UINT16     VendorID;
129   UINT16     DeviceID;
130   UINT16     RevisionID;
131   UINT8      Reserved[6];
132 } ACM_CHIPSET_ID;
133 
134 typedef struct {
135   UINT32           Count;
136   ACM_CHIPSET_ID   ChipsetID[1];
137 } CHIPSET_ID_LIST;
138 
139 typedef struct {
140   UINT32     FMS;
141   UINT32     FMSMask;
142   UINT64     PlatformID;
143   UINT64     PlatformMask;
144 } ACM_PROCESSOR_ID;
145 
146 typedef struct {
147   UINT32           Count;
148   ACM_PROCESSOR_ID ProcessorID[1];
149 } PROCESSOR_ID_LIST;
150 
151 #pragma pack ()
152 
153 
154 ACM_GUID mChipsetAcmInformationTableGuid03 = CHIPSET_ACM_INFORMATION_TABLE_GUID_V03;
155 
156 
157 //
158 // BIOS INFO data structure
159 // This is self contained data structure for BIOS info
160 //
161 #pragma pack (1)
162 #define BIOS_INFO_SIGNATURE  SIGNATURE_64 ('$', 'B', 'I', 'O', 'S', 'I', 'F', '$')
163 typedef struct {
164   UINT64            Signature;
165   UINT32            EntryCount;
166   UINT32            Reserved;
167 //BIOS_INFO_STRUCT  Struct[EntryCount];
168 } BIOS_INFO_HEADER;
169 
170 //
171 // BIOS_INFO_STRUCT attributes
172 // bits[0:3] means general attributes
173 // bits[4:7] means type specific attributes
174 //
175 #define BIOS_INFO_STRUCT_ATTRIBUTE_GENERAL_EXCLUDE_FROM_FIT  0x01
176 #define BIOS_INFO_STRUCT_ATTRIBUTE_MICROCODE_WHOLE_REGION    0x10
177 #define BIOS_INFO_STRUCT_ATTRIBUTE_BIOS_POST_IBB             0x10
178 
179 typedef struct {
180   //
181   // FitTable entry type
182   //
183   UINT8    Type;
184   //
185   // BIOS_INFO_STRUCT attributes
186   //
187   UINT8    Attributes;
188   //
189   // FitTable entry version
190   //
191   UINT16   Version;
192   //
193   // FitTable entry real size
194   //
195   UINT32   Size;
196   //
197   // FitTable entry address
198   //
199   UINT64   Address;
200 } BIOS_INFO_STRUCT;
201 
202 #pragma pack ()
203 
204 #define MAX_BIOS_MODULE_ENTRY  0x20
205 #define MAX_MICROCODE_ENTRY    0x20
206 #define MAX_OPTIONAL_ENTRY     0x20
207 #define MAX_PORT_ENTRY         0x20
208 
209 #define DEFAULT_FIT_TABLE_POINTER_OFFSET  0x40
210 #define DEFAULT_FIT_ENTRY_VERSION         0x0100
211 
212 #define TOP_FLASH_ADDRESS  (gFitTableContext.TopFlashAddressRemapValue)
213 
214 #define MEMORY_TO_FLASH(FileBuffer, FvBuffer, FvSize)  \
215                  (UINTN)(TOP_FLASH_ADDRESS - ((UINTN)(FvBuffer) + (UINTN)(FvSize) - (UINTN)(FileBuffer)))
216 #define FLASH_TO_MEMORY(Address, FvBuffer, FvSize)  \
217                  (VOID *)(UINTN)((UINTN)(FvBuffer) + (UINTN)(FvSize) - (TOP_FLASH_ADDRESS - (UINTN)(Address)))
218 
219 #define FIT_TABLE_TYPE_HEADER                 0
220 #define FIT_TABLE_TYPE_MICROCODE              1
221 #define FIT_TABLE_TYPE_STARTUP_ACM            2
222 #define FIT_TABLE_TYPE_DIAGNST_ACM            3
223 #define FIT_TABLE_TYPE_BIOS_MODULE            7
224 #define FIT_TABLE_TYPE_TPM_POLICY             8
225 #define FIT_TABLE_TYPE_BIOS_POLICY            9
226 #define FIT_TABLE_TYPE_TXT_POLICY             10
227 #define FIT_TABLE_TYPE_KEY_MANIFEST           11
228 #define FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST   12
229 #define FIT_TABLE_TYPE_BIOS_DATA_AREA         13
230 #define FIT_TABLE_TYPE_CSE_SECURE_BOOT        16
231 #define FIT_TABLE_SUBTYPE_FIT_PATCH_MANIFEST  12
232 #define FIT_TABLE_SUBTYPE_ACM_MANIFEST        13
233 
234 //
235 // With OptionalModule Address isn't known until free space has been
236 // identified and the optional module has been copied into the FLASH
237 // image buffer (or initialized to be populated later by another program).
238 // This is very dangerous code as it can truncate 64b pointers to
239 // allocated memory buffers.  The full pointer is in Buffer for that case.
240 //
241 typedef struct {
242   UINT32  Type;
243   UINT32  SubType; // Used by OptionalModule only
244   UINT32  Address;
245   UINT8   *Buffer; // Used by OptionalModule only
246   UINT32  Size;
247   UINT32  Version; // Used by OptionalModule and PortModule only
248 } FIT_TABLE_CONTEXT_ENTRY;
249 
250 typedef struct {
251   BOOLEAN                    Clear;
252   UINT32                     FitTablePointerOffset;
253   UINT32                     FitTablePointerOffset2;
254   UINT32                     FitEntryNumber;
255   UINT32                     BiosModuleNumber;
256   UINT32                     MicrocodeNumber;
257   UINT32                     OptionalModuleNumber;
258   UINT32                     PortModuleNumber;
259   UINT32                     GlobalVersion;
260   UINT32                     FitHeaderVersion;
261   FIT_TABLE_CONTEXT_ENTRY    StartupAcm;
262   UINT32                     StartupAcmVersion;
263   FIT_TABLE_CONTEXT_ENTRY    DiagnstAcm;
264   UINT32                     DiagnstAcmVersion;
265   FIT_TABLE_CONTEXT_ENTRY    BiosModule[MAX_BIOS_MODULE_ENTRY];
266   UINT32                     BiosModuleVersion;
267   FIT_TABLE_CONTEXT_ENTRY    Microcode[MAX_MICROCODE_ENTRY];
268   BOOLEAN                    MicrocodeIsAligned;
269   UINT32                     MicrocodeAlignValue;
270   UINT32                     MicrocodeVersion;
271   FIT_TABLE_CONTEXT_ENTRY    OptionalModule[MAX_OPTIONAL_ENTRY];
272   FIT_TABLE_CONTEXT_ENTRY    PortModule[MAX_PORT_ENTRY];
273   UINT64                     TopFlashAddressRemapValue;
274 } FIT_TABLE_CONTEXT;
275 
276 FIT_TABLE_CONTEXT   gFitTableContext = {0};
277 
278 unsigned int
279 xtoi (
280   char  *str
281   );
282 
283 VOID
PrintUtilityInfo(VOID)284 PrintUtilityInfo (
285   VOID
286   )
287 /*++
288 
289 Routine Description:
290 
291   Displays the standard utility information to STDOUT
292 
293 Arguments:
294 
295   None
296 
297 Returns:
298 
299   None
300 
301 --*/
302 {
303   printf (
304     "%s - Tiano IA32/X64 FIT table generation Utility for FIT spec revision 1.2."" Version %i.%i\n\n",
305     UTILITY_NAME,
306     UTILITY_MAJOR_VERSION,
307     UTILITY_MINOR_VERSION
308     );
309 }
310 
311 VOID
PrintUsage(VOID)312 PrintUsage (
313   VOID
314   )
315 /*++
316 
317 Routine Description:
318 
319   Displays the utility usage syntax to STDOUT
320 
321 Arguments:
322 
323   None
324 
325 Returns:
326 
327   None
328 
329 --*/
330 {
331   printf ("Usage (generate): %s [-D] InputFvRecoveryFile OutputFvRecoveryFile\n"
332           "\t[-V <FitEntryDefaultVersion>]\n"
333           "\t[-F <FitTablePointerOffset>] [-F <FitTablePointerOffset>] [-V <FitHeaderVersion>]\n"
334           "\t[-NA]\n"
335           "\t[-A <MicrocodeAlignment>]\n"
336           "\t[-REMAP <TopFlashAddress>\n"
337           "\t[-CLEAR]\n"
338           "\t[-L <MicrocodeSlotSize> <MicrocodeFfsGuid>]\n"
339           "\t[-LF <MicrocodeSlotSize>]\n"
340           "\t[-I <BiosInfoGuid>]\n"
341           "\t[-S <StartupAcmAddress StartupAcmSize>|<StartupAcmGuid>] [-V <StartupAcmVersion>]\n"
342           "\t[-U <DiagnstAcmAddress>|<DiagnstAcmGuid>]\n"
343           "\t[-B <BiosModuleAddress BiosModuleSize>] [-B ...] [-V <BiosModuleVersion>]\n"
344           "\t[-M <MicrocodeAddress MicrocodeSize>] [-M ...]|[-U <MicrocodeFv MicrocodeBase>|<MicrocodeRegionOffset MicrocodeRegionSize>|<MicrocodeGuid>] [-V <MicrocodeVersion>]\n"
345           "\t[-O RecordType <RecordDataAddress RecordDataSize>|<RESERVE RecordDataSize>|<RecordDataGuid>|<RecordBinFile>|<CseRecordSubType RecordBinFile> [-V <RecordVersion>]] [-O ... [-V ...]]\n"
346           "\t[-P RecordType <IndexPort DataPort Width Bit Index> [-V <RecordVersion>]] [-P ... [-V ...]]\n"
347           , UTILITY_NAME);
348   printf ("  Where:\n");
349   printf ("\t-D                     - It is FD file instead of FV file. (The tool will search FV file)\n");
350   printf ("\tInputFvRecoveryFile    - Name of the input FvRecovery.fv file.\n");
351   printf ("\tOutputFvRecoveryFile   - Name of the output FvRecovery.fv file.\n");
352   printf ("\tFitTablePointerOffset  - FIT table pointer offset. 0x%x as default. 0x18 for current soon to be obsoleted CPUs. User can set both.\n", DEFAULT_FIT_TABLE_POINTER_OFFSET);
353   printf ("\tBiosInfoGuid           - Guid of BiosInfo Module. If this module exists, StartupAcm/Bios/Microcode can be optional.\n");
354   printf ("\tStartupAcmAddress      - Address of StartupAcm.\n");
355   printf ("\tStartupAcmSize         - Size of StartupAcm.\n");
356   printf ("\tStartupAcmGuid         - Guid of StartupAcm Module, if StartupAcm is in a BiosModule, it will be excluded form that.\n");
357   printf ("\tDiagnstAcmAddress      - Address of DiagnstAcm.\n");
358   printf ("\tDiagnstAcmGuid         - Guid of DiagnstAcm Module, if DiagnstAcm is in a BiosModule, it will be excluded from that.\n");
359   printf ("\tBiosModuleAddress      - Address of BiosModule. User should ensure there is no overlap.\n");
360   printf ("\tBiosModuleSize         - Size of BiosModule.\n");
361   printf ("\tMicrocodeAddress       - Address of Microcode.\n");
362   printf ("\tMicrocodeSize          - Size of Microcode.\n");
363   printf ("\tMicrocodeFv            - Name of Microcode.fv file.\n");
364   printf ("\tMicrocodeBase          - The base address of Microcode.fv in final FD image.\n");
365   printf ("\tMicrocodeRegionOffset  - Offset of Microcode region in input FD image.\n");
366   printf ("\tMicrocodeRegionSize    - Size of Microcode region in input FD image.\n");
367   printf ("\tMicrocodeGuid          - Guid of Microcode Module.\n");
368   printf ("\tMicrocodeSlotSize      - Occupied region size of each Microcode binary.\n");
369   printf ("\tMicrocodeFfsGuid       - Guid of FFS which is used to save Microcode binary");
370   printf ("\t-LF                    - Microcode Slot mode without FFS check, treat all Microcode FV as slot mode. In this case the Microcode FV should only contain one FFS.\n");
371   printf ("\t-NA                    - No 0x800 aligned Microcode requirement. No -NA means Microcode is aligned with option MicrocodeAlignment value.\n");
372   printf ("\tMicrocodeAlignment     - HEX value of Microcode alignment. Ignored if \"-NA\" is specified. Default value is 0x800. The Microcode update data must start at a 16-byte aligned linear address.\n");
373   printf ("\tRecordType             - FIT entry record type. User should ensure it is ordered.\n");
374   printf ("\tRecordDataAddress      - FIT entry record data address.\n");
375   printf ("\tRecordDataSize         - FIT entry record data size.\n");
376   printf ("\tRecordDataGuid         - FIT entry record data GUID.\n");
377   printf ("\tRecordBinFile          - FIT entry record data binary file.\n");
378   printf ("\tCseRecordSubType       - FIT entry record subtype. Use to further distinguish CSE entries (see FIT spec revision 1.2 chapter 4.12).\n");
379   printf ("\tFitEntryDefaultVersion - The default version for all FIT table entries. 0x%04x is used if this is not specified.\n", DEFAULT_FIT_ENTRY_VERSION);
380   printf ("\tFitHeaderVersion       - The version for FIT header. (Override default version)\n");
381   printf ("\tStartupAcmVersion      - The version for StartupAcm. (Override default version)\n");
382   printf ("\tBiosModuleVersion      - The version for BiosModule. (Override default version)\n");
383   printf ("\tMicrocodeVersion       - The version for Microcode. (Override default version)\n");
384   printf ("\tRecordVersion          - The version for Record. (Override default version)\n");
385   printf ("\tIndexPort              - The Index Port Number.\n");
386   printf ("\tDataPort               - The Data Port Number.\n");
387   printf ("\tWidth                  - The Width of the port.\n");
388   printf ("\tBit                    - The Bit Number of the port.\n");
389   printf ("\tIndex                  - The Index Number of the port.\n");
390   printf ("\nUsage (view): %s [-view] InputFile -F <FitTablePointerOffset>\n", UTILITY_NAME);
391   printf ("  Where:\n");
392   printf ("\tInputFile              - Name of the input file.\n");
393   printf ("\tFitTablePointerOffset  - FIT table pointer offset from end of file. 0x%x as default.\n", DEFAULT_FIT_TABLE_POINTER_OFFSET);
394   printf ("\nTool return values:\n");
395   printf ("\tSTATUS_SUCCESS=%d, STATUS_WARNING=%d, STATUS_ERROR=%d\n", STATUS_SUCCESS, STATUS_WARNING, STATUS_ERROR);
396 }
397 
398 VOID *
SetMem(OUT VOID * Buffer,IN UINTN Length,IN UINT8 Value)399 SetMem (
400   OUT     VOID                      *Buffer,
401   IN      UINTN                     Length,
402   IN      UINT8                     Value
403   )
404 {
405   //
406   // Declare the local variables that actually move the data elements as
407   // volatile to prevent the optimizer from replacing this function with
408   // the intrinsic memset()
409   //
410   volatile UINT8                    *Pointer;
411 
412   Pointer = (UINT8*)Buffer;
413   while (Length-- > 0) {
414     *(Pointer++) = Value;
415   }
416   return Buffer;
417 }
418 
419 BOOLEAN
CheckPath(IN CHAR8 * String)420 CheckPath (
421   IN CHAR8 * String
422 )
423 {
424   //
425   //Return FLASE if  input file path include % character or is NULL
426   //
427   CHAR8 *StrPtr;
428 
429   StrPtr = String;
430   if (StrPtr == NULL) {
431     return FALSE;
432   }
433 
434   if (*StrPtr == 0) {
435     return FALSE;
436   }
437 
438   while (*StrPtr != '\0') {
439     if (*StrPtr == '%') {
440       return FALSE;
441     }
442     StrPtr++;
443   }
444   return TRUE;
445 }
446 
447 STATUS
ReadInputFile(IN CHAR8 * FileName,OUT UINT8 ** FileData,OUT UINT32 * FileSize,OUT UINT8 ** FileBufferRaw OPTIONAL)448 ReadInputFile (
449   IN CHAR8    *FileName,
450   OUT UINT8   **FileData,
451   OUT UINT32  *FileSize,
452   OUT UINT8   **FileBufferRaw OPTIONAL
453   )
454 /*++
455 
456 Routine Description:
457 
458   Read input file
459 
460 Arguments:
461 
462   FileName      - The input file name
463   FileData      - The input file data, the memory is aligned.
464   FileSize      - The input file size
465   FileBufferRaw - The memory to hold input file data. The caller must free the memory.
466 
467 Returns:
468 
469   STATUS_SUCCESS - The file found and data read
470   STATUS_ERROR   - The file data is not read
471   STATUS_WARNING - The file is not found
472 
473 --*/
474 {
475   FILE                        *FpIn;
476   UINT32                      TempResult;
477 
478   //
479   //Check the File Path
480   //
481   if (!CheckPath(FileName)) {
482 
483     Error (NULL, 0, 0, "File path is invalid!", NULL);
484     return STATUS_ERROR;
485   }
486 
487   //
488   // Open the Input FvRecovery.fv file
489   //
490   if ((FpIn = fopen (FileName, "rb")) == NULL) {
491     //
492     // Return WARNING, let caller make decision
493     //
494 //    Error (NULL, 0, 0, "Unable to open file", FileName);
495     return STATUS_WARNING;
496   }
497   //
498   // Get the Input FvRecovery.fv file size
499   //
500   fseek (FpIn, 0, SEEK_END);
501   *FileSize = ftell (FpIn);
502   //
503   // Read the contents of input file to memory buffer
504   //
505   if (FileBufferRaw != NULL) {
506     *FileBufferRaw = (UINT8 *) malloc (*FileSize + 0x10000);
507     if (NULL == *FileBufferRaw) {
508       Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
509       fclose (FpIn);
510       return STATUS_ERROR;
511     }
512     TempResult = 0x10000 - (UINT32) ((UINTN)*FileBufferRaw & 0x0FFFF);
513     *FileData = (UINT8 *)((UINTN)*FileBufferRaw + TempResult);
514   } else {
515     *FileData = (UINT8 *) malloc (*FileSize);
516      if (NULL == *FileData) {
517       Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
518       fclose (FpIn);
519       return STATUS_ERROR;
520     }
521   }
522   fseek (FpIn, 0, SEEK_SET);
523   TempResult = fread (*FileData, 1, *FileSize, FpIn);
524   if (TempResult != *FileSize) {
525     Error (NULL, 0, 0, "Read input file error!", NULL);
526     if (FileBufferRaw != NULL) {
527       free ((VOID *)*FileBufferRaw);
528     } else {
529       free ((VOID *)*FileData);
530     }
531     fclose (FpIn);
532     return STATUS_ERROR;
533   }
534 
535   //
536   // Close the input FvRecovery.fv file
537   //
538   fclose (FpIn);
539 
540   return STATUS_SUCCESS;
541 }
542 
543 UINT8 *
FindNextFvHeader(IN UINT8 * FileBuffer,IN UINTN FileLength)544 FindNextFvHeader (
545   IN UINT8 *FileBuffer,
546   IN UINTN  FileLength
547   )
548 /*++
549 
550   Routine Description:
551     Find next FvHeader in the FileBuffer
552 
553   Parameters:
554     FileBuffer        -   The start FileBuffer which needs to be searched
555     FileLength        -   The whole File Length.
556   Return:
557     FvHeader          -   The FvHeader is found successfully.
558     NULL              -   The FvHeader is not found.
559 
560 --*/
561 {
562   UINT8                       *FileHeader;
563   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
564   UINT16                      FileChecksum;
565 
566   FileHeader = FileBuffer;
567   for (; (UINTN)FileBuffer < (UINTN)FileHeader + FileLength; FileBuffer += 8) {
568     FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;
569     if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
570       //
571       // potential candidate
572       //
573 
574       //
575       // Check checksum
576       //
577       if (FvHeader->FvLength > FileLength) {
578         continue;
579       }
580       if (FvHeader->HeaderLength >= FileLength) {
581         continue;
582       }
583       FileChecksum = CalculateChecksum16 ((UINT16 *)FileBuffer, FvHeader->HeaderLength / sizeof (UINT16));
584       if (FileChecksum != 0) {
585         continue;
586       }
587 
588       //
589       // Check revision and reserved field
590       //
591 #if (PI_SPECIFICATION_VERSION < 0x00010000)
592       if ((FvHeader->Revision == EFI_FVH_REVISION) &&
593           (FvHeader->Reserved[0] == 0) &&
594           (FvHeader->Reserved[1] == 0) &&
595           (FvHeader->Reserved[2] == 0) ){
596         return FileBuffer;
597       }
598 #else
599       if ((FvHeader->Revision == EFI_FVH_PI_REVISION) &&
600           (FvHeader->Reserved[0] == 0) ){
601         return FileBuffer;
602       }
603 #endif
604     }
605   }
606 
607   return NULL;
608 }
609 
610 UINT8  *
FindFileFromFvByGuid(IN UINT8 * FvBuffer,IN UINT32 FvSize,IN EFI_GUID * Guid,OUT UINT32 * FileSize)611 FindFileFromFvByGuid (
612   IN UINT8     *FvBuffer,
613   IN UINT32    FvSize,
614   IN EFI_GUID  *Guid,
615   OUT UINT32   *FileSize
616   )
617 /*++
618 
619 Routine Description:
620 
621   Find File with GUID in an FV
622 
623 Arguments:
624 
625   FvBuffer       - FV binary buffer
626   FvSize         - FV size
627   Guid           - File GUID value to be searched
628   FileSize       - Guid File size
629 
630 Returns:
631 
632   FileLocation   - Guid File location.
633   NULL           - Guid File is not found.
634 
635 --*/
636 {
637   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
638   EFI_FFS_FILE_HEADER         *FileHeader;
639   UINT64                      FvLength;
640   EFI_GUID                    *TempGuid;
641   UINT8                       *FixPoint;
642   UINTN                       Offset;
643   UINTN                       FileLength;
644   UINTN                       FileOccupiedSize;
645 
646   //
647   // Find the FFS file
648   //
649   FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FindNextFvHeader (FvBuffer, FvSize);
650   if (NULL == FvHeader) {
651     return NULL;
652   }
653   while (TRUE) {
654     FvLength         = FvHeader->FvLength;
655 
656     //
657     // Prepare to walk the FV image
658     //
659     InitializeFvLib (FvHeader, (UINT32)FvLength);
660 
661     FileHeader       = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + FvHeader->HeaderLength);
662     Offset           = (UINTN) FileHeader - (UINTN) FvHeader;
663 
664     while (Offset < FvLength) {
665       TempGuid = (EFI_GUID *)&(FileHeader->Name);
666       FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
667       FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
668       if ((CompareGuid (TempGuid, Guid)) == 0) {
669         //
670         // Good! Find it.
671         //
672         FixPoint = ((UINT8 *)FileHeader + sizeof(EFI_FFS_FILE_HEADER));
673         //
674         // Find the position of file module, the offset
675         // between the position and the end of FvRecovery.fv file
676         // should not exceed 128kB to prevent reset vector from
677         // outside legacy E and F segment
678         //
679         if ((UINTN)FvHeader + FvLength - (UINTN)FixPoint > 0x20000) {
680   //        printf ("WARNING: The position of file module is not in E and F segment!\n");
681   //        return NULL;
682         }
683         *FileSize = FileLength - sizeof(EFI_FFS_FILE_HEADER);
684   #if (PI_SPECIFICATION_VERSION < 0x00010000)
685         if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
686           *FileSize -= sizeof(EFI_FFS_FILE_TAIL);
687         }
688   #endif
689         return FixPoint;
690       }
691       FileHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FileHeader + FileOccupiedSize);
692       Offset = (UINTN) FileHeader - (UINTN) FvHeader;
693     }
694 
695     //
696     // Not found, check next FV
697     //
698     if ((UINTN)FvBuffer + FvSize > (UINTN)FvHeader + FvLength) {
699       FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FindNextFvHeader ((UINT8 *)FvHeader + (UINTN)FvLength, (UINTN)FvBuffer + FvSize - ((UINTN)FvHeader + (UINTN)FvLength));
700       if (FvHeader == NULL) {
701         break;
702       }
703     } else {
704       break;
705     }
706   }
707 
708   //
709   // Not found
710   //
711   return NULL;
712 }
713 
714 BOOLEAN
IsGuidData(IN CHAR8 * StringData,OUT EFI_GUID * Guid)715 IsGuidData (
716   IN CHAR8     *StringData,
717   OUT EFI_GUID *Guid
718   )
719 /*++
720 
721 Routine Description:
722 
723   Check whether a string is a GUID
724 
725 Arguments:
726 
727   StringData  - the String
728   Guid        - Guid to hold the value
729 
730 Returns:
731 
732   TRUE  - StringData is a GUID, and Guid field is filled.
733   FALSE - StringData is not a GUID
734 
735 --*/
736 {
737   if (strlen (StringData) != strlen ("00000000-0000-0000-0000-000000000000")) {
738     return FALSE;
739   }
740   if ((StringData[8] != '-') ||
741       (StringData[13] != '-') ||
742       (StringData[18] != '-') ||
743       (StringData[23] != '-') ) {
744     return FALSE;
745   }
746 
747   StringToGuid (StringData, Guid);
748 
749   return TRUE;
750 }
751 
752 VOID
CheckOverlap(IN UINT32 Address,IN UINT32 Size)753 CheckOverlap (
754   IN UINT32 Address,
755   IN UINT32 Size
756   )
757 {
758   INTN  Index;
759 
760   for (Index = 0; Index < (INTN)gFitTableContext.BiosModuleNumber; Index ++) {
761     if ((gFitTableContext.BiosModule[Index].Address <= Address) &&
762         ((gFitTableContext.BiosModule[Index].Size - Size) >= (Address - gFitTableContext.BiosModule[Index].Address))) {
763       UINT32  TempSize;
764       INT32   SubIndex;
765 
766       //
767       // Found overlap, split BiosModuleEntry
768       // Currently only support StartupAcm in 1 BiosModule. It does not support StartupAcm across 2 BiosModule or more.
769       //
770       if (gFitTableContext.BiosModuleNumber >= MAX_BIOS_MODULE_ENTRY) {
771         Error (NULL, 0, 0, "Too many Bios Module!", NULL);
772         return ;
773       }
774 
775       if (Address != gFitTableContext.BiosModule[Index].Address) {
776         //
777         // Skip the entry whose start address is same as StartupAcm
778         //
779         gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type    = FIT_TABLE_TYPE_BIOS_MODULE;
780         gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Address = gFitTableContext.BiosModule[Index].Address;
781         gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    = Address - gFitTableContext.BiosModule[Index].Address;
782         gFitTableContext.BiosModuleNumber ++;
783         gFitTableContext.FitEntryNumber++;
784       }
785 
786       TempSize = gFitTableContext.BiosModule[Index].Address + gFitTableContext.BiosModule[Index].Size;
787       gFitTableContext.BiosModule[Index].Address = Address + Size;
788       gFitTableContext.BiosModule[Index].Size    = TempSize - gFitTableContext.BiosModule[Index].Address;
789 
790       if (gFitTableContext.BiosModule[Index].Size == 0) {
791         //
792         // remove the entry if size is 0
793         //
794         for (SubIndex = Index; SubIndex < (INTN)gFitTableContext.BiosModuleNumber - 1; SubIndex ++) {
795           gFitTableContext.BiosModule[SubIndex].Address = gFitTableContext.BiosModule[SubIndex + 1].Address;
796           gFitTableContext.BiosModule[SubIndex].Size    = gFitTableContext.BiosModule[SubIndex + 1].Size;
797         }
798         gFitTableContext.BiosModuleNumber --;
799         gFitTableContext.FitEntryNumber--;
800       }
801       break;
802     }
803   }
804 }
805 
806 UINT8 *
GetMicrocodeBufferFromFv(EFI_FIRMWARE_VOLUME_HEADER * FvHeader)807 GetMicrocodeBufferFromFv (
808   EFI_FIRMWARE_VOLUME_HEADER *FvHeader
809   )
810 {
811   UINT8 *MicrocodeBuffer;
812   EFI_FFS_FILE_HEADER *FfsHeader;
813 
814   MicrocodeBuffer = NULL;
815   //
816   // Skip FV header + FV extension header + FFS header
817   //
818   FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *) FvHeader + FvHeader->HeaderLength);
819   while ((UINT8 *) FfsHeader < (UINT8 *) FvHeader + FvHeader->FvLength) {
820     if (FfsHeader->Type == EFI_FV_FILETYPE_RAW) {
821       //
822       // Find the first RAW ffs file as Microcode Buffer
823       //
824       MicrocodeBuffer = (UINT8 *)(FfsHeader + 1);
825       break;
826     }
827     if (GetFfsFileLength (FfsHeader) == 0xFFFFFF) {
828       // spare space is found, and exit
829       break;
830     }
831     FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + ((GetFfsFileLength (FfsHeader)+7)&~7));
832   }
833 
834   return MicrocodeBuffer;
835 }
836 
837 UINT32
GetFitEntryNumber(IN INTN argc,IN CHAR8 ** argv,IN UINT8 * FdBuffer,IN UINT32 FdSize)838 GetFitEntryNumber (
839   IN INTN   argc,
840   IN CHAR8  **argv,
841   IN UINT8  *FdBuffer,
842   IN UINT32 FdSize
843   )
844 /*++
845 
846 Routine Description:
847 
848   Get FIT entry number and fill global FIT table context, from argument
849 
850 Arguments:
851 
852   argc           - Number of command line parameters.
853   argv           - Array of pointers to parameter strings.
854   FdBuffer       - FD binary buffer
855   FdSize         - FD size
856 
857 Returns:
858 
859   FitEntryNumber - The FIT entry number
860   0              - Argument parse fail
861 
862 */
863 {
864   EFI_GUID  Guid;
865   EFI_GUID  MicrocodeFfsGuid;
866   INTN      Index;
867   UINT8     *FileBuffer;
868   UINT32    FileSize;
869   UINT32    Type;
870   UINT32    SubType;
871   UINT8     *MicrocodeFileBuffer;
872   UINT8     *MicrocodeFileBufferRaw;
873   UINT32    MicrocodeFileSize;
874   UINT32    MicrocodeBase;
875   UINT32    MicrocodeSize;
876   UINT8     *MicrocodeBuffer;
877   UINT32    MicrocodeBufferSize;
878   UINT8     *Walker;
879   UINT32    MicrocodeRegionOffset;
880   UINT32    MicrocodeRegionSize;
881   UINT32    SlotSize;
882   STATUS    Status;
883   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
884   UINTN                       FitEntryNumber;
885   BOOLEAN                     BiosInfoExist;
886   BOOLEAN                     SlotMode;
887   BOOLEAN                     SlotModeForce;
888   BIOS_INFO_HEADER            *BiosInfo;
889   BIOS_INFO_STRUCT            *BiosInfoStruct;
890   UINTN                       BiosInfoIndex;
891 
892   SlotMode      = FALSE;
893   SlotModeForce = FALSE;
894 
895   //
896   // Init index
897   //
898   Index = 3;
899   if (((strcmp (argv[1], "-D") == 0) ||
900        (strcmp (argv[1], "-d") == 0)) ) {
901     Index ++;
902   }
903 
904   //
905   // Fill Global Version
906   //
907   if ((Index + 1 >= argc) ||
908       ((strcmp (argv[Index], "-V") != 0) &&
909        (strcmp (argv[Index], "-v") != 0)) ) {
910     gFitTableContext.GlobalVersion = DEFAULT_FIT_ENTRY_VERSION;
911   } else {
912     gFitTableContext.GlobalVersion = xtoi (argv[Index + 1]);
913     Index += 2;
914   }
915 
916   //
917   // 0. FIT Header
918   //
919   gFitTableContext.FitEntryNumber = 1;
920   if ((Index + 1 >= argc) ||
921       ((strcmp (argv[Index], "-F") != 0) &&
922        (strcmp (argv[Index], "-f") != 0)) ) {
923     //
924     // Use default address
925     //
926     gFitTableContext.FitTablePointerOffset = DEFAULT_FIT_TABLE_POINTER_OFFSET;
927   } else {
928     //
929     // Get offset from parameter
930     //
931     gFitTableContext.FitTablePointerOffset = xtoi (argv[Index + 1]);
932     Index += 2;
933   }
934 
935   //
936   // 0.1 FIT Header 2
937   //
938   if ((Index + 1 >= argc) ||
939       ((strcmp (argv[Index], "-F") != 0) &&
940        (strcmp (argv[Index], "-f") != 0)) ) {
941     //
942     // Bypass
943     //
944     gFitTableContext.FitTablePointerOffset2 = 0;
945   } else {
946     //
947     // Get offset from parameter
948     //
949     gFitTableContext.FitTablePointerOffset2 = xtoi (argv[Index + 1]);
950     Index += 2;
951   }
952 
953   //
954   // 0.2 FIT Header version
955   //
956   if ((Index + 1 >= argc) ||
957       ((strcmp (argv[Index], "-V") != 0) &&
958        (strcmp (argv[Index], "-v") != 0)) ) {
959     //
960     // Bypass
961     //
962     gFitTableContext.FitHeaderVersion = gFitTableContext.GlobalVersion;
963   } else {
964     //
965     // Get offset from parameter
966     //
967     gFitTableContext.FitHeaderVersion = xtoi (argv[Index + 1]);
968     Index += 2;
969   }
970 
971   //
972   // 0.3 Microcode alignment
973   //
974   if ((Index >= argc) ||
975       ((strcmp (argv[Index], "-NA") != 0) &&
976        (strcmp (argv[Index], "-na") != 0) &&
977        (strcmp (argv[Index], "-A") != 0) &&
978        (strcmp (argv[Index], "-a") != 0))) {
979     //
980     // by pass
981     //
982     gFitTableContext.MicrocodeIsAligned = TRUE;
983     gFitTableContext.MicrocodeAlignValue = 0x800;
984   } else if ((strcmp (argv[Index], "-NA") == 0) || (strcmp (argv[Index], "-na") == 0)) {
985     gFitTableContext.MicrocodeIsAligned = FALSE;
986     gFitTableContext.MicrocodeAlignValue = 1;
987     Index += 1;
988   } else if ((strcmp (argv[Index], "-A") == 0) || (strcmp (argv[Index], "-a") == 0)) {
989     gFitTableContext.MicrocodeIsAligned = TRUE;
990     //
991     // Get alignment from parameter
992     //
993     gFitTableContext.MicrocodeAlignValue = xtoi (argv[Index + 1]);;
994     Index += 2;
995   }
996 
997   if ((Index >= argc) ||
998       ((strcmp (argv[Index], "-REMAP") == 0) ||
999        (strcmp (argv[Index], "-remap") == 0)) ) {
1000     //
1001     // by pass
1002     //
1003     gFitTableContext.TopFlashAddressRemapValue = xtoi (argv[Index + 1]);
1004     Index += 2;
1005   } else {
1006     //
1007     // no remapping
1008     //
1009     gFitTableContext.TopFlashAddressRemapValue = 0x100000000;
1010   }
1011   printf ("Top Flash Address Value : 0x%llx\n", (unsigned long long) gFitTableContext.TopFlashAddressRemapValue);
1012   //
1013   // 0.4 Clear FIT table related memory
1014   //
1015   if ((Index >= argc) ||
1016       ((strcmp (argv[Index], "-CLEAR") != 0) &&
1017        (strcmp (argv[Index], "-clear") != 0)) ) {
1018     //
1019     // by pass
1020     //
1021     gFitTableContext.Clear = FALSE;
1022   } else {
1023     //
1024     // Clear FIT table
1025     //
1026     gFitTableContext.Clear = TRUE;
1027     //
1028     // Do not parse any more
1029     //
1030     return 0;
1031   }
1032 
1033   //
1034   // 0.5 SlotSize
1035   //
1036   if ((Index + 1 >= argc) ||
1037       ((strcmp (argv[Index], "-L") != 0) &&
1038        (strcmp (argv[Index], "-l") != 0) &&
1039        (strcmp (argv[Index], "-LF") != 0) &&
1040        (strcmp (argv[Index], "-lf") != 0))) {
1041     //
1042     // Bypass
1043     //
1044     SlotSize = 0;
1045   } else {
1046     SlotSize = xtoi (argv[Index + 1]);
1047 
1048     if (SlotSize == 0 || SlotSize & 0xF) {
1049       printf ("Invalid slotsize = 0x%x, slot size should not be zero, or start at a non-16-byte aligned linear address!\n", SlotSize);
1050       return 0;
1051     }
1052     if (strcmp (argv[Index], "-LF") == 0 || strcmp (argv[Index], "-lf") == 0) {
1053       SlotModeForce = TRUE;
1054       Index += 2;
1055     } else {
1056       SlotMode = IsGuidData(argv[Index + 2], &MicrocodeFfsGuid);
1057       if (!SlotMode) {
1058         printf ("Need a ffs GUID for search uCode ffs\n");
1059         return 0;
1060       }
1061       Index += 3;
1062     }
1063   }
1064 
1065   //
1066   // 0.6 BiosInfo
1067   //
1068   if ((Index + 1 >= argc) ||
1069       ((strcmp (argv[Index], "-I") != 0) &&
1070        (strcmp (argv[Index], "-i") != 0)) ) {
1071     //
1072     // Bypass
1073     //
1074     BiosInfoExist = FALSE;
1075   } else {
1076     //
1077     // Get offset from parameter
1078     //
1079     BiosInfoExist = TRUE;
1080     if (IsGuidData (argv[Index + 1], &Guid)) {
1081       FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
1082       if (FileBuffer == NULL) {
1083         Error (NULL, 0, 0, "-I Parameter incorrect, GUID not found!", "%s", argv[Index + 1]);
1084         // not found
1085         return 0;
1086       }
1087       BiosInfo = (BIOS_INFO_HEADER *)FileBuffer;
1088       for (BiosInfoIndex = 0; BiosInfoIndex < FileSize; BiosInfoIndex++) {
1089         if (((BIOS_INFO_HEADER *)(FileBuffer + BiosInfoIndex))->Signature == BIOS_INFO_SIGNATURE) {
1090           BiosInfo = (BIOS_INFO_HEADER *)(FileBuffer + BiosInfoIndex);
1091         }
1092       }
1093       if (BiosInfo->Signature != BIOS_INFO_SIGNATURE) {
1094         Error (NULL, 0, 0, "-I Parameter incorrect, Signature Error!", NULL);
1095         // not found
1096         return 0;
1097       }
1098       BiosInfoStruct = (BIOS_INFO_STRUCT *)(BiosInfo + 1);
1099 
1100       for (BiosInfoIndex = 0; BiosInfoIndex < BiosInfo->EntryCount; BiosInfoIndex++) {
1101         if ((BiosInfoStruct[BiosInfoIndex].Attributes & BIOS_INFO_STRUCT_ATTRIBUTE_GENERAL_EXCLUDE_FROM_FIT) != 0) {
1102           continue;
1103         }
1104         switch (BiosInfoStruct[BiosInfoIndex].Type) {
1105         case FIT_TABLE_TYPE_HEADER:
1106           Error (NULL, 0, 0, "-I Parameter incorrect, Header Type unsupported!", NULL);
1107           return 0;
1108         case FIT_TABLE_TYPE_STARTUP_ACM:
1109           if (gFitTableContext.StartupAcm.Type != 0) {
1110             Error (NULL, 0, 0, "-I Parameter incorrect, Duplicated StartupAcm!", NULL);
1111             return 0;
1112           }
1113           gFitTableContext.StartupAcm.Type    = FIT_TABLE_TYPE_STARTUP_ACM;
1114           gFitTableContext.StartupAcm.Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1115           gFitTableContext.StartupAcm.Size    = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
1116           gFitTableContext.StartupAcmVersion  = BiosInfoStruct[BiosInfoIndex].Version;
1117           gFitTableContext.FitEntryNumber ++;
1118           break;
1119         case FIT_TABLE_TYPE_DIAGNST_ACM:
1120           if (gFitTableContext.DiagnstAcm.Type != 0) {
1121             Error (NULL, 0, 0, "-U Parameter incorrect, Duplicated DiagnosticsAcm!", NULL);
1122             return 0;
1123           }
1124           gFitTableContext.DiagnstAcm.Type    = FIT_TABLE_TYPE_DIAGNST_ACM;
1125           gFitTableContext.DiagnstAcm.Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1126           gFitTableContext.DiagnstAcm.Size    = 0;
1127           gFitTableContext.DiagnstAcmVersion  = DEFAULT_FIT_ENTRY_VERSION;
1128           gFitTableContext.FitEntryNumber ++;
1129           break;
1130         case FIT_TABLE_TYPE_BIOS_MODULE:
1131           if ((BiosInfoStruct[BiosInfoIndex].Attributes & BIOS_INFO_STRUCT_ATTRIBUTE_BIOS_POST_IBB) != 0) {
1132             continue;
1133           }
1134           if (gFitTableContext.BiosModuleNumber >= MAX_BIOS_MODULE_ENTRY) {
1135             Error (NULL, 0, 0, "-I Parameter incorrect, Too many Bios Module!", NULL);
1136             return 0;
1137           }
1138           gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type    = FIT_TABLE_TYPE_BIOS_MODULE;
1139           gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1140           gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
1141           gFitTableContext.BiosModuleVersion = BiosInfoStruct[BiosInfoIndex].Version;
1142           gFitTableContext.BiosModuleNumber ++;
1143           gFitTableContext.FitEntryNumber ++;
1144           break;
1145         case FIT_TABLE_TYPE_MICROCODE:
1146           if ((BiosInfoStruct[BiosInfoIndex].Attributes & BIOS_INFO_STRUCT_ATTRIBUTE_MICROCODE_WHOLE_REGION) == 0) {
1147             if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
1148               Error (NULL, 0, 0, "-I Parameter incorrect, Too many Microcode!", NULL);
1149               return 0;
1150             }
1151             gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type    = FIT_TABLE_TYPE_MICROCODE;
1152             gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1153             gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size    = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
1154             gFitTableContext.MicrocodeVersion = BiosInfoStruct[BiosInfoIndex].Version;
1155             gFitTableContext.MicrocodeNumber++;
1156             gFitTableContext.FitEntryNumber++;
1157           } else {
1158             MicrocodeRegionOffset = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1159             MicrocodeRegionSize   = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
1160             if (MicrocodeRegionOffset == 0) {
1161               Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionOffset is 0", NULL);
1162               return 0;
1163             }
1164             if (MicrocodeRegionSize == 0) {
1165               Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionSize is 0", NULL);
1166               return 0;
1167             }
1168             if (MicrocodeRegionSize > FdSize) {
1169               Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionSize too large", NULL);
1170               return 0;
1171             }
1172 
1173             MicrocodeFileBuffer = FLASH_TO_MEMORY (MicrocodeRegionOffset, FdBuffer, FdSize);
1174             MicrocodeFileSize = MicrocodeRegionSize;
1175             MicrocodeBase = MicrocodeRegionOffset;
1176 
1177             FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)MicrocodeFileBuffer;
1178             if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
1179               MicrocodeBuffer = GetMicrocodeBufferFromFv (FvHeader);
1180             } else {
1181               MicrocodeBuffer = MicrocodeFileBuffer;
1182             }
1183 
1184             if (SlotMode) {
1185               MicrocodeBuffer = FindFileFromFvByGuid(MicrocodeFileBuffer, MicrocodeFileSize, &MicrocodeFfsGuid, &MicrocodeBufferSize);
1186               if (MicrocodeBuffer == NULL) {
1187                 printf ("-L Parameter incorrect, GUID not found\n");
1188                 // not found
1189                 return 0;
1190               }
1191             }
1192 
1193             while ((UINT32)(MicrocodeBuffer - MicrocodeFileBuffer) < MicrocodeFileSize) {
1194               if (*(UINT32 *)(MicrocodeBuffer) != 0x1) { // HeaderVersion
1195                 break;
1196               }
1197               if (*(UINT32 *)(MicrocodeBuffer + 20) != 0x1) { // LoaderVersion
1198                 break;
1199               }
1200               if (*(UINT32 *)(MicrocodeBuffer + 28) == 0) { // DataSize
1201                 MicrocodeSize = 2048;
1202               } else {
1203                 //
1204                 // MCU might be put at 2KB alignment, if so, we need to adjust the size as 2KB alignment.
1205                 //
1206                 if (gFitTableContext.MicrocodeIsAligned) {
1207                   if (gFitTableContext.MicrocodeAlignValue & 0xF) {
1208                     printf ("-A Parameter incorrect, Microcode data must start at a 16-byte aligned linear address!\n");
1209                     return 0;
1210                   }
1211                   MicrocodeSize = ROUNDUP (*(UINT32 *)(MicrocodeBuffer + 32), gFitTableContext.MicrocodeAlignValue);
1212                 } else {
1213                   MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32));
1214                 }
1215               }
1216 
1217               //
1218               // Add Microcode
1219               //
1220               if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
1221                 printf ("-I Parameter incorrect, Too many Microcode!\n");
1222                 return 0;
1223               }
1224               gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type = FIT_TABLE_TYPE_MICROCODE;
1225               gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = MicrocodeBase + (UINT32)((UINTN) MicrocodeBuffer - (UINTN) MicrocodeFileBuffer);
1226               gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size = MicrocodeSize;
1227               gFitTableContext.MicrocodeNumber++;
1228               gFitTableContext.FitEntryNumber++;
1229 
1230               if (SlotSize != 0) {
1231                 if (SlotSize < MicrocodeSize) {
1232                   printf ("Parameter incorrect, Slot size: %x is too small for Microcode size: %x!\n", SlotSize, MicrocodeSize);
1233                   return 0;
1234                 }
1235                 MicrocodeBuffer += SlotSize;
1236               } else {
1237                 MicrocodeBuffer += MicrocodeSize;
1238               }
1239             }
1240 
1241             ///
1242             /// Check the remaining buffer
1243             ///
1244             if (((UINT32)(MicrocodeBuffer - MicrocodeFileBuffer) < MicrocodeFileSize) && (SlotMode || SlotModeForce)) {
1245               for (Walker = MicrocodeBuffer; Walker < MicrocodeFileBuffer + MicrocodeFileSize; Walker++) {
1246                 if (*Walker != 0xFF) {
1247                   printf ("Error: detect non-spare space after uCode array, please check uCode array!\n");
1248                   return 0;
1249                 }
1250               }
1251 
1252               ///
1253               /// Split the spare space as empty buffer for save uCode patch.
1254               ///
1255               while (MicrocodeBuffer + SlotSize <= MicrocodeFileBuffer + MicrocodeFileSize) {
1256                 gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type = FIT_TABLE_TYPE_MICROCODE;
1257                 gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = MicrocodeBase + (UINT32)((UINTN) MicrocodeBuffer - (UINTN) MicrocodeFileBuffer);
1258                 gFitTableContext.MicrocodeNumber++;
1259                 gFitTableContext.FitEntryNumber++;
1260 
1261                 MicrocodeBuffer += SlotSize;
1262               }
1263             }
1264           }
1265           break;
1266         case FIT_TABLE_TYPE_TPM_POLICY:
1267         case FIT_TABLE_TYPE_BIOS_POLICY:
1268         case FIT_TABLE_TYPE_TXT_POLICY:
1269         case FIT_TABLE_TYPE_KEY_MANIFEST:
1270         case FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST:
1271         case FIT_TABLE_TYPE_BIOS_DATA_AREA:
1272         case FIT_TABLE_TYPE_CSE_SECURE_BOOT:
1273         default :
1274           if (BiosInfoStruct[BiosInfoIndex].Version != 0) {
1275             if (gFitTableContext.OptionalModuleNumber >= MAX_OPTIONAL_ENTRY) {
1276               Error (NULL, 0, 0, "-I Parameter incorrect, Too many Optional Module!", NULL);
1277               return 0;
1278             }
1279             gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Type    = BiosInfoStruct[BiosInfoIndex].Type;
1280             gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1281             gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Size    = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
1282             gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Version = BiosInfoStruct[BiosInfoIndex].Version;
1283             gFitTableContext.OptionalModuleNumber++;
1284             gFitTableContext.FitEntryNumber++;
1285           } else {
1286             if (gFitTableContext.PortModuleNumber >= MAX_PORT_ENTRY) {
1287               Error (NULL, 0, 0, "-I Parameter incorrect, Too many Port Module!", NULL);
1288               return 0;
1289             }
1290             gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type    = BiosInfoStruct[BiosInfoIndex].Type;
1291             gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
1292             gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size    = (UINT32)(BiosInfoStruct[BiosInfoIndex].Address >> 32);
1293             gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version = BiosInfoStruct[BiosInfoIndex].Version;
1294             gFitTableContext.PortModuleNumber++;
1295             gFitTableContext.FitEntryNumber++;
1296           }
1297           break;
1298         }
1299       }
1300 
1301     } else {
1302       Error (NULL, 0, 0, "-I Parameter incorrect, expect GUID!", NULL);
1303       return 0;
1304     }
1305     Index += 2;
1306   }
1307 
1308   //
1309   // 1. StartupAcm
1310   //
1311   do {
1312     if ((Index + 1 >= argc) ||
1313         ((strcmp (argv[Index], "-S") != 0) &&
1314          (strcmp (argv[Index], "-s") != 0)) ) {
1315       if (BiosInfoExist && (gFitTableContext.StartupAcm.Type == FIT_TABLE_TYPE_STARTUP_ACM)) {
1316         break;
1317       }
1318 //      Error (NULL, 0, 0, "-S Parameter incorrect, expect -S!", NULL);
1319 //      return 0;
1320       printf ("-S not found. WARNING!\n");
1321       break;
1322     }
1323     if (IsGuidData (argv[Index + 1], &Guid)) {
1324       FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
1325       if (FileBuffer == NULL) {
1326         Error (NULL, 0, 0, "-S Parameter incorrect, GUID not found!", "%s", argv[Index + 1]);
1327         // not found
1328         return 0;
1329       }
1330       FileBuffer = (UINT8 *)MEMORY_TO_FLASH (FileBuffer, FdBuffer, FdSize);
1331       Index += 2;
1332     } else {
1333       if (Index + 2 >= argc) {
1334         Error (NULL, 0, 0, "-S Parameter incorrect, expect Address Size!", NULL);
1335         return 0;
1336       }
1337       FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
1338       FileSize = xtoi (argv[Index + 2]);
1339       Index += 3;
1340     }
1341     if (gFitTableContext.StartupAcm.Type != 0) {
1342       Error (NULL, 0, 0, "-S Parameter incorrect, Duplicated StartupAcm!", NULL);
1343       return 0;
1344     }
1345     gFitTableContext.StartupAcm.Type = FIT_TABLE_TYPE_STARTUP_ACM;
1346     gFitTableContext.StartupAcm.Address = (UINT32) (UINTN) FileBuffer;
1347     gFitTableContext.StartupAcm.Size = FileSize;
1348     gFitTableContext.FitEntryNumber ++;
1349 
1350     //
1351     // 1.1 StartupAcm version
1352     //
1353     if ((Index + 1 >= argc) ||
1354         ((strcmp (argv[Index], "-V") != 0) &&
1355          (strcmp (argv[Index], "-v") != 0)) ) {
1356       //
1357       // Bypass
1358       //
1359       gFitTableContext.StartupAcmVersion = gFitTableContext.GlobalVersion;
1360     } else {
1361       //
1362       // Get offset from parameter
1363       //
1364       gFitTableContext.StartupAcmVersion = xtoi (argv[Index + 1]);
1365       Index += 2;
1366     }
1367   } while (FALSE);
1368 
1369   //
1370   // 1.5. DiagnosticsAcm
1371   //
1372   do {
1373     if ((Index + 1 >= argc) ||
1374         ((strcmp (argv[Index], "-U") != 0) &&
1375          (strcmp (argv[Index], "-u") != 0)) ) {
1376       if (BiosInfoExist && (gFitTableContext.DiagnstAcm.Type == FIT_TABLE_TYPE_DIAGNST_ACM)) {
1377         break;
1378       }
1379       break;
1380     }
1381     if (IsGuidData (argv[Index + 1], &Guid)) {
1382       FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
1383       if (FileBuffer == NULL) {
1384         Error (NULL, 0, 0, "-U Parameter incorrect, GUID not found!", "%s", argv[Index + 1]);
1385         return 0;
1386       }
1387       FileBuffer = (UINT8 *)MEMORY_TO_FLASH (FileBuffer, FdBuffer, FdSize);
1388       Index += 2;
1389     } else {
1390       FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
1391       Index += 2;
1392     }
1393     if (gFitTableContext.DiagnstAcm.Type != 0) {
1394       Error (NULL, 0, 0, "-U Parameter incorrect, Duplicated DiagnosticsAcm!", NULL);
1395       return 0;
1396     }
1397     gFitTableContext.DiagnstAcm.Type = FIT_TABLE_TYPE_DIAGNST_ACM;
1398     gFitTableContext.DiagnstAcm.Address = (UINT32) (UINTN) FileBuffer;
1399     gFitTableContext.DiagnstAcm.Size = 0;
1400     gFitTableContext.FitEntryNumber ++;
1401     gFitTableContext.DiagnstAcmVersion = DEFAULT_FIT_ENTRY_VERSION;
1402   } while (FALSE);
1403 
1404   // 2. BiosModule
1405   //
1406   do {
1407     if ((Index + 2 >= argc) ||
1408         ((strcmp (argv[Index], "-B") != 0) &&
1409          (strcmp (argv[Index], "-b") != 0)) ) {
1410       if (BiosInfoExist && (gFitTableContext.BiosModuleNumber != 0)) {
1411         break;
1412       }
1413 //      Error (NULL, 0, 0, "-B Parameter incorrect, expect -B!", NULL);
1414 //      return 0;
1415       printf ("-B not found. WARNING!\n");
1416       break;
1417     }
1418 
1419     FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
1420     FileSize = xtoi (argv[Index + 2]);
1421     gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type = FIT_TABLE_TYPE_BIOS_MODULE;
1422     gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Address = (UINT32) (UINTN) FileBuffer;
1423     gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size = FileSize;
1424     gFitTableContext.BiosModuleNumber ++;
1425     gFitTableContext.FitEntryNumber ++;
1426 
1427     while (TRUE) {
1428       Index += 3;
1429       if (Index + 2 >= argc) {
1430         break;
1431       }
1432       if ((strcmp (argv[Index], "-B") != 0) &&
1433           (strcmp (argv[Index], "-b") != 0) ) {
1434         break;
1435       }
1436       if (gFitTableContext.BiosModuleNumber >= MAX_BIOS_MODULE_ENTRY) {
1437         Error (NULL, 0, 0, "-B Parameter incorrect, Too many Bios Module!", NULL);
1438         return 0;
1439       }
1440       FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
1441       FileSize = xtoi (argv[Index + 2]);
1442       gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type = FIT_TABLE_TYPE_BIOS_MODULE;
1443       gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Address = (UINT32) (UINTN) FileBuffer;
1444       gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size = FileSize;
1445       gFitTableContext.BiosModuleNumber ++;
1446       gFitTableContext.FitEntryNumber++;
1447     }
1448 
1449     //
1450     // 2.1 BiosModule version
1451     //
1452     if ((Index + 1 >= argc) ||
1453         ((strcmp (argv[Index], "-V") != 0) &&
1454          (strcmp (argv[Index], "-v") != 0)) ) {
1455       //
1456       // Bypass
1457       //
1458       gFitTableContext.BiosModuleVersion = gFitTableContext.GlobalVersion;
1459     } else {
1460       //
1461       // Get offset from parameter
1462       //
1463       gFitTableContext.BiosModuleVersion = xtoi (argv[Index + 1]);
1464       Index += 2;
1465     }
1466   } while (FALSE);
1467 
1468   //
1469   // 3. Microcode
1470   //
1471   while (TRUE) {
1472     if (Index + 1 >= argc) {
1473       break;
1474     }
1475     if ((strcmp (argv[Index], "-M") != 0) &&
1476         (strcmp (argv[Index], "-m") != 0) ) {
1477       break;
1478     }
1479     if (IsGuidData (argv[Index + 2], &Guid)) {
1480       Error (NULL, 0, 0, "-M Parameter incorrect, GUID unsupported!", NULL);
1481       return 0;
1482     } else {
1483       if (Index + 2 >= argc) {
1484         break;
1485       }
1486       FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
1487       FileSize = xtoi (argv[Index + 2]);
1488       Index += 3;
1489     }
1490     if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
1491       Error (NULL, 0, 0, "-M Parameter incorrect, Too many Microcode!", NULL);
1492       return 0;
1493     }
1494     gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type = FIT_TABLE_TYPE_MICROCODE;
1495     gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = (UINT32) (UINTN) FileBuffer;
1496     gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size = FileSize;
1497     gFitTableContext.MicrocodeNumber++;
1498     gFitTableContext.FitEntryNumber++;
1499   }
1500 
1501   //
1502   // 3.1 MicrocodeFv
1503   //
1504   while (TRUE) {
1505     if (Index + 1 >= argc) {
1506       break;
1507     }
1508     if ((strcmp (argv[Index], "-U") != 0) &&
1509         (strcmp (argv[Index], "-u") != 0) ) {
1510       break;
1511     }
1512     //
1513     // Get Fv
1514     //
1515     if (IsGuidData (argv[Index + 1], &Guid)) {
1516       MicrocodeFileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &MicrocodeFileSize);
1517       if (MicrocodeFileBuffer == NULL) {
1518         Error (NULL, 0, 0, "-U Parameter incorrect, GUID not found!", "%s", argv[Index + 1]);
1519         // not found
1520         return 0;
1521       }
1522       Index += 2;
1523 
1524       MicrocodeBuffer = MicrocodeFileBuffer;
1525       MicrocodeFileBufferRaw = NULL;
1526       MicrocodeRegionOffset = MEMORY_TO_FLASH (MicrocodeFileBuffer, FdBuffer, FdSize);
1527       MicrocodeRegionSize   = 0;
1528       MicrocodeBase = MicrocodeRegionOffset;
1529 
1530     } else {
1531       if (Index + 2 >= argc) {
1532         break;
1533       }
1534       Status = ReadInputFile (argv[Index + 1], &MicrocodeFileBuffer, &MicrocodeFileSize, &MicrocodeFileBufferRaw);
1535       if (Status != STATUS_SUCCESS) {
1536         MicrocodeRegionOffset = xtoi (argv[Index + 1]);
1537         MicrocodeRegionSize   = xtoi (argv[Index + 2]);
1538 
1539         if (MicrocodeRegionOffset == 0) {
1540           Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionOffset is 0, or unable to open file", "%s", argv[Index + 1]);
1541           return 0;
1542         }
1543         if (MicrocodeRegionSize == 0) {
1544           Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionSize is 0", NULL);
1545           return 0;
1546         }
1547         if (MicrocodeRegionSize > FdSize) {
1548           Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionSize too large", NULL);
1549           return 0;
1550         }
1551 
1552         Index += 3;
1553 
1554         MicrocodeFileBufferRaw = NULL;
1555         MicrocodeFileBuffer = FLASH_TO_MEMORY (MicrocodeRegionOffset, FdBuffer, FdSize);
1556         MicrocodeFileSize = MicrocodeRegionSize;
1557         MicrocodeBase = MicrocodeRegionOffset;
1558 
1559         FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)MicrocodeFileBuffer;
1560         if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
1561           MicrocodeBuffer = GetMicrocodeBufferFromFv (FvHeader);
1562         } else {
1563           MicrocodeBuffer = MicrocodeFileBuffer;
1564         }
1565       } else {
1566         MicrocodeBase = xtoi (argv[Index + 2]);
1567         Index += 3;
1568         MicrocodeRegionOffset = 0;
1569         MicrocodeRegionSize   = 0;
1570 
1571         FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)MicrocodeFileBuffer;
1572         if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
1573           MicrocodeBuffer = GetMicrocodeBufferFromFv (FvHeader);
1574         } else {
1575           MicrocodeBuffer = MicrocodeFileBuffer;
1576         }
1577       }
1578     }
1579     while ((UINT32)(MicrocodeBuffer - MicrocodeFileBuffer) < MicrocodeFileSize) {
1580       if (*(UINT32 *)(MicrocodeBuffer) != 0x1) { // HeaderVersion
1581         break;
1582       }
1583       if (*(UINT32 *)(MicrocodeBuffer + 20) != 0x1) { // LoaderVersion
1584         break;
1585       }
1586       if (*(UINT32 *)(MicrocodeBuffer + 28) == 0) { // DataSize
1587         MicrocodeSize = 2048;
1588       } else {
1589         //
1590         // MCU might be put at 2KB alignment, if so, we need to adjust the size as 2KB alignment.
1591         //
1592         if (gFitTableContext.MicrocodeIsAligned) {
1593           MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32) + (gFitTableContext.MicrocodeAlignValue - 1)) & ~(gFitTableContext.MicrocodeAlignValue - 1);
1594         } else {
1595           MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32));
1596         }
1597       }
1598 
1599       //
1600       // Add Microcode
1601       //
1602       if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
1603         printf ("-U Parameter incorrect, Too many Microcode!\n");
1604         return 0;
1605       }
1606       gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type = FIT_TABLE_TYPE_MICROCODE;
1607       gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = MicrocodeBase + (UINT32)((UINTN) MicrocodeBuffer - (UINTN) MicrocodeFileBuffer);
1608       gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size = MicrocodeSize;
1609       gFitTableContext.MicrocodeNumber++;
1610       gFitTableContext.FitEntryNumber++;
1611 
1612       MicrocodeBuffer += MicrocodeSize;
1613     }
1614 
1615     if (MicrocodeFileBufferRaw != NULL) {
1616       free ((VOID *)MicrocodeFileBufferRaw);
1617       MicrocodeFileBufferRaw = NULL;
1618     }
1619   }
1620 
1621   //
1622   // 3.3 Microcode version
1623   //
1624   if ((Index + 1 >= argc) ||
1625       ((strcmp (argv[Index], "-V") != 0) &&
1626        (strcmp (argv[Index], "-v") != 0)) ) {
1627     //
1628     // Bypass
1629     //
1630     gFitTableContext.MicrocodeVersion = gFitTableContext.GlobalVersion;
1631   } else {
1632     //
1633     // Get offset from parameter
1634     //
1635     gFitTableContext.MicrocodeVersion = xtoi (argv[Index + 1]);
1636     Index += 2;
1637   }
1638 
1639   //
1640   // 4. Optional type
1641   //
1642   while (TRUE) {
1643     if (Index + 2 >= argc) {
1644       break;
1645     }
1646     if ((strcmp (argv[Index], "-O") != 0) &&
1647         (strcmp (argv[Index], "-o") != 0) ) {
1648       break;
1649     }
1650     Type = xtoi (argv[Index + 1]);
1651     //
1652     // 1st, try CSE entry sub-type
1653     //
1654     SubType = 0;
1655     if (Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT) {
1656       if (Index + 3 >= argc) {
1657         break;
1658       }
1659       SubType = xtoi (argv[Index + 2]);
1660       //
1661       // try file
1662       //
1663       if (SubType != FIT_TABLE_SUBTYPE_FIT_PATCH_MANIFEST && SubType != FIT_TABLE_SUBTYPE_ACM_MANIFEST) {
1664         Error (NULL, 0, 0, "-O Parameter incorrect, SubType unsupported!", NULL);
1665         return 0;
1666       }
1667       Status = ReadInputFile (argv[Index + 3], &FileBuffer, &FileSize, NULL);
1668       if (Status == STATUS_SUCCESS) {
1669         if (FileSize >= 0x80000000) {
1670           Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
1671           free (FileBuffer);
1672           return 0;
1673         }
1674         //
1675         // Set the most significant bit
1676         // It means the data in memory, not in flash yet.
1677         // Assume the file size should < 2G.
1678         //
1679         FileSize |= 0x80000000;
1680         Index += 4;
1681       } else {
1682         if (Status == STATUS_WARNING) {
1683           Error (NULL, 0, 0, "-O Parameter incorrect, Unable to open file", argv[Index + 3]);
1684         }
1685         return 0;
1686       }
1687     } else {
1688       //
1689       // 2nd, try GUID
1690       //
1691       if (IsGuidData (argv[Index + 2], &Guid)) {
1692         FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
1693         if (FileBuffer == NULL) {
1694           Error (NULL, 0, 0, "-O Parameter incorrect, GUID not found!", "%s", argv[Index + 2]);
1695           // not found
1696           return 0;
1697         }
1698         if (FileSize >= 0x80000000) {
1699           Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
1700           return 0;
1701         }
1702       FileBuffer = (UINT8 *)MEMORY_TO_FLASH (FileBuffer, FdBuffer, FdSize);
1703         Index += 3;
1704       } else {
1705         //
1706         // 3rd, try file
1707         //
1708         Status = ReadInputFile (argv[Index + 2], &FileBuffer, &FileSize, NULL);
1709         if (Status == STATUS_SUCCESS) {
1710           if (FileSize >= 0x80000000) {
1711             Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
1712             free (FileBuffer);
1713             return 0;
1714           }
1715           //
1716           // Set the most significant bit
1717           // It means the data in memory, not in flash yet.
1718           // Assume the file size should < 2G.
1719           //
1720           FileSize |= 0x80000000;
1721           Index += 3;
1722         } else {
1723           //
1724           // 4th, try <RESERVE, Length>
1725           //
1726           if (Index + 3 >= argc) {
1727             break;
1728           }
1729           if ((strcmp (argv[Index + 2], "RESERVE") == 0) ||
1730               (strcmp (argv[Index + 2], "reserve") == 0)) {
1731             FileSize = xtoi (argv[Index + 3]);
1732             if (FileSize >= 0x80000000) {
1733               Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
1734               return 0;
1735             }
1736             FileBuffer = malloc (FileSize);
1737             if (FileBuffer == NULL) {
1738               Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
1739               return 0;
1740             }
1741             SetMem (FileBuffer, FileSize, 0xFF);
1742             //
1743             // Set the most significant bit
1744             // It means the data in memory, not in flash yet.
1745             // Assume the file size should < 2G.
1746             //
1747             FileSize |= 0x80000000;
1748             Index += 4;
1749           } else {
1750             //
1751             // 5th, try <Address, Length>
1752             //
1753             if (Index + 3 >= argc) {
1754               break;
1755             }
1756             FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 2]);
1757             FileSize = xtoi (argv[Index + 3]);
1758             if (FileSize >= 0x80000000) {
1759               Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
1760               return 0;
1761             }
1762             Index += 4;
1763           }
1764         }
1765       }
1766     }
1767     if (gFitTableContext.OptionalModuleNumber >= MAX_OPTIONAL_ENTRY) {
1768       Error (NULL, 0, 0, "-O Parameter incorrect, Too many Optional Module!", NULL);
1769       free (FileBuffer);
1770       return 0;
1771     }
1772     gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Type = Type;
1773     if (gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT) {
1774       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].SubType = SubType;
1775     }
1776     gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Address = (UINT32) (UINTN) FileBuffer;
1777     gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Buffer = FileBuffer;
1778     gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Size = FileSize;
1779 
1780     //
1781     // 4.1 Optional Module version
1782     //
1783     if ((Index + 1 >= argc) ||
1784         ((strcmp (argv[Index], "-V") != 0) &&
1785          (strcmp (argv[Index], "-v") != 0)) ) {
1786       //
1787       // Bypass
1788       //
1789       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Version = gFitTableContext.GlobalVersion;
1790     } else {
1791       //
1792       // Get offset from parameter
1793       //
1794       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Version = xtoi (argv[Index + 1]);
1795       Index += 2;
1796     }
1797 
1798     gFitTableContext.OptionalModuleNumber ++;
1799     gFitTableContext.FitEntryNumber++;
1800   }
1801 
1802   //
1803   // 5. Port type
1804   //
1805   while (TRUE) {
1806     if (Index + 6 >= argc) {
1807       break;
1808     }
1809     if ((strcmp (argv[Index], "-P") != 0) &&
1810         (strcmp (argv[Index], "-p") != 0) ) {
1811       break;
1812     }
1813 
1814     Type = xtoi (argv[Index + 1]);
1815     if (gFitTableContext.PortModuleNumber >= MAX_PORT_ENTRY) {
1816       printf ("-P Parameter incorrect, Too many Port Module!\n");
1817       return 0;
1818     }
1819 
1820     gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type = Type;
1821     gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Address = (UINT16)xtoi (argv[Index + 2]) + ((UINT16)xtoi (argv[Index + 3]) << 16);
1822     gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size = (UINT8)xtoi (argv[Index + 4]) + ((UINT8)xtoi (argv[Index + 5]) << 8) + ((UINT16)xtoi (argv[Index + 6]) << 16);
1823     Index += 7;
1824 
1825     //
1826     // 5.1 Port Module version
1827     //
1828     if ((Index + 1 >= argc) ||
1829         ((strcmp (argv[Index], "-V") != 0) &&
1830          (strcmp (argv[Index], "-v") != 0)) ) {
1831       //
1832       // Bypass
1833       //
1834       gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version = 0;
1835     } else {
1836       //
1837       // Get offset from parameter
1838       //
1839       gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version = xtoi (argv[Index + 1]);
1840       Index += 2;
1841     }
1842 
1843     gFitTableContext.PortModuleNumber++;
1844     gFitTableContext.FitEntryNumber++;
1845   }
1846 
1847   //
1848   // Final: Check StartupAcm in BiosModule.
1849   //
1850   CheckOverlap (gFitTableContext.StartupAcm.Address, gFitTableContext.StartupAcm.Size);
1851   FitEntryNumber = gFitTableContext.FitEntryNumber;
1852   for (Index = 0; Index < (INTN)gFitTableContext.OptionalModuleNumber; Index++) {
1853     if ((gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_POLICY) ||
1854         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_KEY_MANIFEST) ||
1855         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
1856         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
1857         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
1858       // NOTE: It might be virtual address now. Just put a place holder.
1859       FitEntryNumber ++;
1860     }
1861   }
1862 
1863   return FitEntryNumber;
1864 }
1865 
1866 VOID *
FindSpaceSkipApVector(IN UINT8 * FvBuffer,IN UINT8 * Address,IN UINTN Size)1867 FindSpaceSkipApVector (
1868   IN UINT8     *FvBuffer,
1869   IN UINT8     *Address,
1870   IN UINTN     Size
1871   )
1872 /*++
1873 
1874 Routine Description:
1875 
1876   No enough space - it might happen that it is occupied by AP wake vector.
1877   Last chance - skip this and search again.
1878 
1879 Arguments:
1880 
1881   FvBuffer       - FvRecovery binary buffer
1882   Address        - Address to be searched from
1883   Size           - Size need to be filled
1884 
1885 Returns:
1886 
1887   FitTableOffset - The FIT table offset
1888   NULL           - No enough space for FIT table
1889 
1890 */
1891 {
1892   UINT8        *ApVector;
1893   UINT8        *NewAddress;
1894   UINTN        Index;
1895 
1896   ApVector = (UINT8 *)((UINTN)Address & ~0xFFF);
1897   if ((UINTN)ApVector <= (UINTN)FvBuffer) {
1898     return NULL;
1899   }
1900 
1901   NewAddress = (UINT8 *)(ApVector - Size);
1902   for (Index = 0; Index < Size; Index ++) {
1903     if (NewAddress[Index] != 0xFF) {
1904       return NULL;
1905     }
1906   }
1907   return NewAddress;
1908 }
1909 
1910 VOID *
GetFreeSpaceFromFv(IN UINT8 * FvBuffer,IN UINT32 FvSize,IN UINT32 FitEntryNumber)1911 GetFreeSpaceFromFv (
1912   IN UINT8     *FvBuffer,
1913   IN UINT32    FvSize,
1914   IN UINT32    FitEntryNumber
1915   )
1916 /*++
1917 
1918 Routine Description:
1919 
1920   Get free space for FIT table from FvRecovery
1921 
1922 Arguments:
1923 
1924   FvBuffer       - FvRecovery binary buffer
1925   FvSize         - FvRecovery size
1926   FitEntryNumber - The FIT entry number
1927 
1928 Returns:
1929 
1930   FitTableOffset - The offset of FIT table in FvRecovery file
1931   NULL           - Free space not found
1932 
1933 --*/
1934 {
1935   UINT8       *FitTableOffset;
1936   INTN        Index;
1937   INTN        SubIndex;
1938   UINT8       *OptionalModuleAddress;
1939   EFI_GUID    VTFGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1940   UINT32      AlignedSize;
1941   UINT32      FitTableSize;
1942 
1943   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
1944   EFI_FFS_FILE_HEADER         *FileHeader;
1945   UINT64                      FvLength;
1946   UINT32                      Offset;
1947   UINT32                      FileLength;
1948   UINT32                      FileOccupiedSize;
1949 
1950   //
1951   // Check 4G - FitTablePointerOffset
1952   //
1953   if ((*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) != 0xFFFFFFFFFFFFFFFFull) &&
1954       (*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) != 0) &&
1955       (*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) != 0xEEEEEEEEEEEEEEEEull)) {
1956     Error (NULL, 0, 0, "4G - FitTablePointerOffset is occupied!", NULL);
1957     return NULL;
1958   }
1959   if (gFitTableContext.FitTablePointerOffset2 != 0) {
1960     if ((*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2) != 0xFFFFFFFFFFFFFFFFull) &&
1961         (*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2) != 0) &&
1962         (*(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2) != 0xEEEEEEEEEEEEEEEEull)) {
1963       Error (NULL, 0, 0, "4G - FitTablePointerOffset is occupied!", NULL);
1964       return NULL;
1965     }
1966   }
1967 
1968   //
1969   // Get EFI_FFS_VOLUME_TOP_FILE_GUID location
1970   //
1971   FitTableOffset = NULL;
1972 
1973   FvHeader         = (EFI_FIRMWARE_VOLUME_HEADER *)FvBuffer;
1974   FvLength         = FvHeader->FvLength;
1975   FileHeader       = (EFI_FFS_FILE_HEADER *)(FvBuffer + FvHeader->HeaderLength);
1976   Offset           = (UINTN)FileHeader - (UINTN)FvBuffer;
1977 
1978   while (Offset < FvLength) {
1979     FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
1980     FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
1981     if ((CompareGuid (&(FileHeader->Name), &VTFGuid)) == 0) {
1982       // find it
1983       FitTableOffset = (UINT8 *)FileHeader;
1984       break;
1985     }
1986     FileHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FileHeader + FileOccupiedSize);
1987     Offset = (UINTN)FileHeader - (UINTN)FvBuffer;
1988   }
1989 
1990   if (FitTableOffset == NULL) {
1991     Error (NULL, 0, 0, "EFI_FFS_VOLUME_TOP_FILE_GUID not found!", NULL);
1992     return NULL;
1993   }
1994 
1995   FitTableSize = FitEntryNumber * sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY);
1996   FitTableSize += FIT_ALIGNMENT;
1997   FitTableSize &= ~FIT_ALIGNMENT;
1998 
1999   FitTableOffset = (UINT8 *)((UINTN)FitTableOffset & ~FIT_ALIGNMENT);
2000   FitTableOffset = (UINT8 *)(FitTableOffset - FitTableSize);
2001 
2002   //
2003   // Check it
2004   //
2005   for (Index = 0; Index < (INTN)(FitTableSize); Index ++) {
2006     if (FitTableOffset[Index] != 0xFF) {
2007       //
2008       // No enough space - it might happen that it is occupied by AP wake vector.
2009       // Last chance - skip this and search again.
2010       //
2011       FitTableOffset = FindSpaceSkipApVector (FvBuffer, &FitTableOffset[Index], FitTableSize);
2012       if (FitTableOffset == NULL) {
2013         Error (NULL, 0, 0, "No enough space for FIT table!", NULL);
2014         return NULL;
2015       }
2016     }
2017   }
2018 
2019   //
2020   // Check space for Optional module
2021   //
2022   OptionalModuleAddress = FitTableOffset;
2023   for (Index = 0; Index < (INTN)gFitTableContext.OptionalModuleNumber; Index++) {
2024     AlignedSize = gFitTableContext.OptionalModule[Index].Size;
2025     if ((gFitTableContext.OptionalModule[Index].Size & 0x80000000) != 0) {
2026 
2027       //
2028       // Need copy binary to file.
2029       //
2030       gFitTableContext.OptionalModule[Index].Size &= ~0x80000000;
2031 
2032       AlignedSize = gFitTableContext.OptionalModule[Index].Size;
2033       if ((gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_POLICY) ||
2034           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_KEY_MANIFEST) ||
2035           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
2036           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
2037           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
2038         // Let it 64 byte align
2039         AlignedSize += BIOS_MODULE_ALIGNMENT;
2040         AlignedSize &= ~BIOS_MODULE_ALIGNMENT;
2041       }
2042 
2043       OptionalModuleAddress -= AlignedSize;
2044 
2045       if ((gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_POLICY) ||
2046           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_KEY_MANIFEST) ||
2047           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
2048           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
2049           (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
2050         // Let it 64 byte align
2051         OptionalModuleAddress = (UINT8 *)((UINTN)OptionalModuleAddress & ~BIOS_MODULE_ALIGNMENT);
2052       }
2053 
2054       for (SubIndex = 0; SubIndex < (INTN)(AlignedSize); SubIndex ++) {
2055         if (OptionalModuleAddress[SubIndex] != 0xFF) {
2056           //
2057           // No enough space - it might happen that it is occupied by AP wake vector.
2058           // Last chance - skip this and search again.
2059           //
2060           OptionalModuleAddress = FindSpaceSkipApVector (FvBuffer, &OptionalModuleAddress[SubIndex], AlignedSize);
2061           if (OptionalModuleAddress == NULL) {
2062             Error (NULL, 0, 0, "No enough space for OptionalModule!", NULL);
2063             return NULL;
2064           }
2065         }
2066       }
2067       memcpy (OptionalModuleAddress, gFitTableContext.OptionalModule[Index].Buffer, gFitTableContext.OptionalModule[Index].Size);
2068       free (gFitTableContext.OptionalModule[Index].Buffer);
2069       gFitTableContext.OptionalModule[Index].Address = MEMORY_TO_FLASH (OptionalModuleAddress, FvBuffer, FvSize);
2070     }
2071     //
2072     // Final: Check BiosPolicyData in BiosModule.
2073     //
2074     if ((gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_POLICY) ||
2075         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_KEY_MANIFEST) ||
2076         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
2077         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
2078         (gFitTableContext.OptionalModule[Index].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
2079       CheckOverlap (gFitTableContext.OptionalModule[Index].Address, AlignedSize);
2080     }
2081   }
2082 
2083   return FitTableOffset;
2084 }
2085 
2086 VOID
PrintFitData(VOID)2087 PrintFitData (
2088   VOID
2089   )
2090 /*++
2091 
2092 Routine Description:
2093 
2094   Output FIT table information
2095 
2096 Arguments:
2097 
2098   None
2099 
2100 Returns:
2101 
2102   None
2103 
2104 --*/
2105 {
2106   UINT32                          Index;
2107 
2108   printf ("FIT Table Pointer Offset: 0x%x\n", gFitTableContext.FitTablePointerOffset);
2109   if (gFitTableContext.FitTablePointerOffset2 != 0) {
2110     printf ("FIT Table Pointer Offset: 0x%x\n", gFitTableContext.FitTablePointerOffset2);
2111   }
2112   printf ("Total FIT Entry number: 0x%x\n", gFitTableContext.FitEntryNumber);
2113   printf ("FitHeader version: 0x%04x\n", gFitTableContext.FitHeaderVersion);
2114   if (gFitTableContext.StartupAcm.Address != 0) {
2115     printf ("StartupAcm - (0x%08x, 0x%08x, 0x%04x)\n", gFitTableContext.StartupAcm.Address, gFitTableContext.StartupAcm.Size, gFitTableContext.StartupAcmVersion);
2116   }
2117   if (gFitTableContext.DiagnstAcm.Address != 0) {
2118     printf ("DiagnosticAcm - (0x%08x, 0x%08x, 0x%04x)\n", gFitTableContext.DiagnstAcm.Address, gFitTableContext.DiagnstAcm.Size, gFitTableContext.DiagnstAcmVersion);
2119   }
2120   for (Index = 0; Index < gFitTableContext.BiosModuleNumber; Index++) {
2121     printf ("BiosModule[%d] - (0x%08x, 0x%08x, 0x%04x)\n", Index, gFitTableContext.BiosModule[Index].Address, gFitTableContext.BiosModule[Index].Size, gFitTableContext.BiosModuleVersion);
2122   }
2123   for (Index = 0; Index < gFitTableContext.MicrocodeNumber; Index++) {
2124     printf ("Microcode[%d] - (0x%08x, 0x%08x, 0x%04x)\n", Index, gFitTableContext.Microcode[Index].Address, gFitTableContext.Microcode[Index].Size, gFitTableContext.MicrocodeVersion);
2125   }
2126   for (Index = 0; Index < gFitTableContext.OptionalModuleNumber; Index++) {
2127     printf ("OptionalModule[%d] - (0x%08x, 0x%08x, 0x%02x, 0x%04x)\n", Index, gFitTableContext.OptionalModule[Index].Address, gFitTableContext.OptionalModule[Index].Size, gFitTableContext.OptionalModule[Index].Type, gFitTableContext.OptionalModule[Index].Version);
2128   }
2129   for (Index = 0; Index < gFitTableContext.PortModuleNumber; Index++) {
2130     printf ("PortModule[%d] - (0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%04x, 0x%02x, 0x%04x)\n", Index,
2131       (UINT16)gFitTableContext.PortModule[Index].Address, (UINT16)(gFitTableContext.PortModule[Index].Address >> 16),
2132       (UINT8)gFitTableContext.PortModule[Index].Size, (UINT8)(gFitTableContext.PortModule[Index].Size >> 8), (UINT16)(gFitTableContext.PortModule[Index].Size >> 16),
2133       gFitTableContext.PortModule[Index].Type, gFitTableContext.PortModule[Index].Version);
2134   }
2135 
2136   printf ("\n");
2137   return ;
2138 }
2139 
2140 CHAR8 *mFitCseSubTypeStr[] = {
2141   "CSE_RSVD   ",
2142   "CSE_K_HASH1",
2143   "CSE_M_HASH ",
2144   "CSE_BPOLICY",
2145   "CSE_OTHR_BP",
2146   "CSE_OEMSMIP",
2147   "CSE_MRCDATA",
2148   "CSE_IBBL_H ",
2149   "CSE_IBB_H  ",
2150   "CSE_OEM_ID ",
2151   "CSEOEMSKUID",
2152   "CSE_BD_IND ",
2153   "CSE_FPM    ",
2154   "CSE_ACMM   "
2155 };
2156 
2157 CHAR8 *mFitTypeStr[] = {
2158   "           ",
2159   "MICROCODE  ",
2160   "STARTUP_ACM",
2161   "DIAGNST_ACM",
2162   "           ",
2163   "           ",
2164   "           ",
2165   "           ",
2166   "BIOS_MODULE",
2167   "TPM_POLICY ",
2168   "BIOS_POLICY",
2169   "TXT_POLICY ",
2170   "KEYMANIFEST",
2171   "BP_MANIFEST",
2172   "BIOS_DATA_A",
2173   " ",
2174   " ",
2175   "CSE_SECUREB"
2176 };
2177 
2178 CHAR8  mFitSignature[] = "'_FIT_   ' ";
2179 CHAR8  mFitSignatureInHeader[] = "'        ' ";
2180 CHAR8 *
FitTypeToStr(IN FIRMWARE_INTERFACE_TABLE_ENTRY * FitEntry)2181 FitTypeToStr (
2182   IN FIRMWARE_INTERFACE_TABLE_ENTRY  *FitEntry
2183   )
2184 /*++
2185 
2186 Routine Description:
2187 
2188   Convert FitEntry type to a string
2189 
2190 Arguments:
2191 
2192   FitEntry - Fit entry
2193 
2194 Returns:
2195 
2196   String
2197 
2198 --*/
2199 {
2200   if (FitEntry->Type == FIT_TABLE_TYPE_HEADER) {
2201     CopyMem (&mFitSignatureInHeader[1], &FitEntry->Address, sizeof(FitEntry->Address));
2202     return mFitSignatureInHeader;
2203   }
2204   if (FitEntry->Type < sizeof (mFitTypeStr)/sizeof(mFitTypeStr[0])) {
2205     if (FitEntry->Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT) {
2206       //
2207       // "Reserved" field is used to distinguish CSE Secure Boot entries (see FIT spec revision 1.2)
2208       //
2209       if (FitEntry->Rsvd < sizeof (mFitCseSubTypeStr)/sizeof(mFitCseSubTypeStr[0])) {
2210         return mFitCseSubTypeStr[FitEntry->Rsvd];
2211       }
2212     }
2213     return mFitTypeStr[FitEntry->Type];
2214   } else {
2215     return "           ";
2216   }
2217 }
2218 
2219 VOID
PrintFitTable(IN UINT8 * FvBuffer,IN UINT32 FvSize)2220 PrintFitTable (
2221   IN UINT8                       *FvBuffer,
2222   IN UINT32                      FvSize
2223   )
2224 /*++
2225 
2226 Routine Description:
2227 
2228   Print Fit table in flash image
2229 
2230 Arguments:
2231 
2232   FvBuffer       - FvRecovery binary buffer
2233   FvSize         - FvRecovery size
2234 
2235 Returns:
2236 
2237   None
2238 
2239 --*/
2240 {
2241   FIRMWARE_INTERFACE_TABLE_ENTRY  *FitEntry;
2242   UINT32                          EntryNum;
2243   UINT32                          Index;
2244   UINT32                          FitTableOffset;
2245   FIRMWARE_INTERFACE_TABLE_ENTRY_PORT   *FitEntryPort;
2246 
2247   printf ("##############\n");
2248   printf ("# FIT Table: #\n");
2249   printf ("##############\n");
2250 
2251   printf ("FIT Pointer Offset: 0x%x\n", gFitTableContext.FitTablePointerOffset);
2252   FitTableOffset = *(UINT32 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset);
2253   printf ("FIT Table Address:  0x%x\n", FitTableOffset);
2254   FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FLASH_TO_MEMORY(FitTableOffset, FvBuffer, FvSize);
2255 
2256   //
2257   // Check FitEntry is 16 byte aligned
2258   //
2259   if (((UINTN)FitEntry & 0xF) != 0) {
2260     printf("ERROR: invalid FitEntry address 0x%X!\n", (UINT32) (UINTN) FitEntry);
2261     return;
2262   }
2263 
2264   EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
2265   printf ("====== ================ ====== ======== ============== ==== ======== (====== ==== ====== ==== ======)\n");
2266   printf ("Index:      Address      Size  Version       Type      C_V  Checksum (Index  Data Width  Bit  Offset)\n");
2267   printf ("====== ================ ====== ======== ============== ==== ======== (====== ==== ====== ==== ======)\n");
2268   for (Index = 0; Index < EntryNum; Index++) {
2269     printf (" %02d:   %016llx %06x   %04x   %02x-%s  %02x     %02x   ",
2270       Index,
2271       (unsigned long long) FitEntry[Index].Address,
2272       *(UINT32 *)(&FitEntry[Index].Size[0]) & 0xFFFFFF,
2273       FitEntry[Index].Version,
2274       FitEntry[Index].Type,
2275       FitTypeToStr(&FitEntry[Index]),
2276       FitEntry[Index].C_V,
2277       FitEntry[Index].Checksum
2278       );
2279 
2280     if (Index == 0) {
2281       if (FitEntry[Index].Type != FIT_TABLE_TYPE_HEADER) {
2282         printf("ERROR: FIT Entry 0 is not Header Type %d!\n", FIT_TABLE_TYPE_HEADER);
2283         return;
2284       }
2285       if (strcmp(mFitSignatureInHeader, mFitSignature) != 0) {
2286         printf("ERROR: FIT Entry 0 signature invalid (%s, expected %s)!\n", mFitSignatureInHeader, mFitSignature);
2287         return;
2288       }
2289 
2290     }
2291 
2292     switch (FitEntry[Index].Type) {
2293     case FIT_TABLE_TYPE_TPM_POLICY:
2294     case FIT_TABLE_TYPE_TXT_POLICY:
2295       if (FitEntry[Index].Version == 0) {
2296         FitEntryPort = (FIRMWARE_INTERFACE_TABLE_ENTRY_PORT *)&FitEntry[Index];
2297         printf (" ( %04x  %04x   %02x    %02x   %04x )\n",
2298           FitEntryPort->IndexPort,
2299           FitEntryPort->DataPort,
2300           FitEntryPort->Width,
2301           FitEntryPort->Bit,
2302           FitEntryPort->Index
2303           );
2304         break;
2305       }
2306       // Not Port Configure, pass through
2307     default:
2308       printf ("\n");
2309       break;
2310     }
2311   }
2312   printf ("====== ================ ====== ======== ============== ==== ======== (====== ==== ====== ==== ======)\n");
2313   printf ("Index:      Address      Size  Version       Type      C_V  Checksum (Index  Data Width  Bit  Offset)\n");
2314   printf ("====== ================ ====== ======== ============== ==== ======== (====== ==== ====== ==== ======)\n");
2315 }
2316 
2317 /**
2318 
2319   This function dump raw data.
2320 
2321   @param  Data  raw data
2322   @param  Size  raw data size
2323 
2324 **/
2325 VOID
DumpData(IN UINT8 * Data,IN UINT32 Size)2326 DumpData (
2327   IN UINT8  *Data,
2328   IN UINT32 Size
2329   )
2330 {
2331   UINT32 Index;
2332   for (Index = 0; Index < Size; Index++) {
2333     printf ("%02x", Data[Index]);
2334   }
2335 }
2336 
2337 /**
2338 
2339   This function dump raw data with colume format.
2340 
2341   @param  Data  raw data
2342   @param  Size  raw data size
2343 
2344 **/
2345 VOID
DumpHex(IN UINT8 * Data,IN UINT32 Size)2346 DumpHex (
2347   IN UINT8  *Data,
2348   IN UINT32 Size
2349   )
2350 {
2351   UINT32  Index;
2352   UINT32  Count;
2353   UINT32  Left;
2354 
2355 #define COLUME_SIZE  (16 * 2)
2356 
2357   Count = Size / COLUME_SIZE;
2358   Left  = Size % COLUME_SIZE;
2359   for (Index = 0; Index < Count; Index++) {
2360     printf ("%04x: ", Index * COLUME_SIZE);
2361     DumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
2362     printf ("\n");
2363   }
2364 
2365   if (Left != 0) {
2366     printf ("%04x: ", Index * COLUME_SIZE);
2367     DumpData (Data + Index * COLUME_SIZE, Left);
2368     printf ("\n");
2369   }
2370 }
2371 
2372 //
2373 // This table defines the ACM type string
2374 //
2375 CHAR8 *mAcmTypeStr[] = {
2376   "BIOS ACM",
2377   "SINIT ACM",
2378 };
2379 
2380 //
2381 // This table defines the ACM capability string
2382 //
2383 CHAR8 *mCapabilityStr[] = {
2384   "GETSEC[WAKEUP] for RLP   ",
2385   "MONITOR address for RLP  ",
2386   "ECX for MLE PageTable    ",
2387   "STM support              ",
2388 };
2389 
2390 VOID
DumpAcm(IN ACM_FORMAT * Acm)2391 DumpAcm (
2392   IN ACM_FORMAT                    *Acm
2393   )
2394 /*++
2395 
2396 Routine Description:
2397 
2398   DumpAcm information
2399 
2400 Arguments:
2401 
2402   Acm       - ACM buffer
2403 
2404 Returns:
2405 
2406   None
2407 
2408 --*/
2409 {
2410   CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable;
2411   CHIPSET_ID_LIST               *ChipsetIdList;
2412   PROCESSOR_ID_LIST             *ProcessorIdList;
2413   UINT32                        Index;
2414   UINT8                         *Buffer;
2415 
2416   printf (
2417     "*****************************************************************************\n"
2418     "*         ACM                                                               *\n"
2419     "*****************************************************************************\n"
2420     );
2421 
2422   printf ("ACM: (%08x)\n", (UINT32) (UINTN) Acm);
2423   printf ("  ModuleType                 - %04x\n", Acm->ModuleType);
2424   if (Acm->ModuleType == ACM_MODULE_TYPE_CHIPSET_ACM) {
2425     printf ("    Chipset ACM\n");
2426   }
2427   printf ("  ModuleSubType              - %04x\n", Acm->ModuleSubType);
2428   if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_CAPABLE_OF_EXECUTE_AT_RESET) != 0) {
2429     printf ("    Capable of be Executed at Reset\n");
2430   }
2431   if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) != 0) {
2432     printf ("    AnC Module\n");
2433   }
2434   printf ("  HeaderLen                  - %08x\n", Acm->HeaderLen);
2435   printf ("  HeaderVersion              - %08x\n", Acm->HeaderVersion);
2436   printf ("  ChipsetID                  - %04x\n", Acm->ChipsetID);
2437   printf ("  Flags                      - %04x\n", Acm->Flags);
2438   printf ("    PreProduction            - %04x\n", Acm->Flags & ACM_MODULE_FLAG_PREPRODUCTION);
2439   printf ("    Debug Signed             - %04x\n", Acm->Flags & ACM_MODULE_FLAG_DEBUG_SIGN);
2440   printf ("  ModuleVendor               - %08x\n", Acm->ModuleVendor);
2441   printf ("  Date                       - %08x\n", Acm->Date);
2442   printf ("  Size                       - %08x\n", Acm->Size);
2443   printf ("  TxtSvn                     - %04x\n", Acm->TxtSvn);
2444   printf ("  SeSvn                      - %04x\n", Acm->SeSvn);
2445   printf ("  CodeControl                - %08x\n", Acm->CodeControl);
2446   printf ("  ErrorEntryPoint            - %08x\n", Acm->ErrorEntryPoint);
2447   printf ("  GDTLimit                   - %08x\n", Acm->GDTLimit);
2448   printf ("  GDTBasePtr                 - %08x\n", Acm->GDTBasePtr);
2449   printf ("  SegSel                     - %08x\n", Acm->SegSel);
2450   printf ("  EntryPoint                 - %08x\n", Acm->EntryPoint);
2451   printf ("  KeySize                    - %08x\n", Acm->KeySize);
2452   printf ("  ScratchSize                - %08x\n", Acm->ScratchSize);
2453 
2454   Buffer = (UINT8 *)(Acm + 1);
2455   printf ("  RSAPubKey                  - \n");
2456   DumpHex (Buffer, Acm->KeySize * 4);
2457   printf ("\n");
2458   Buffer += Acm->KeySize * 4;
2459 
2460   if (Acm->HeaderVersion == ACM_HEADER_VERSION_3) {
2461     printf ("  RSASig                     - \n");
2462     DumpHex (Buffer, ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE); // PKCS #1.5 RSA Signature
2463     printf ("\n");
2464     Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE;
2465   } else {
2466     printf ("  RSAPubExp                  - %08x\n", *(UINT32 *)Buffer);
2467     Buffer += 4;
2468 
2469     printf ("  RSASig                     - \n");
2470     DumpHex (Buffer, ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE); // PKCS #1.5 RSA Signature
2471     printf ("\n");
2472     Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE;
2473   }
2474   Buffer += Acm->ScratchSize * 4;
2475 
2476   if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) == 0) {
2477     ChipsetAcmInformationTable = (CHIPSET_ACM_INFORMATION_TABLE *)Buffer;
2478     printf ("Chipset ACM info:\n");
2479     printf (
2480       "  Guid                       - {%08x-%08x-%08x-%08x}\n",
2481       ChipsetAcmInformationTable->Guid.Guid0,
2482       ChipsetAcmInformationTable->Guid.Guid1,
2483       ChipsetAcmInformationTable->Guid.Guid2,
2484       ChipsetAcmInformationTable->Guid.Guid3
2485       );
2486     printf ("  ChipsetACMType             - %02x\n", ChipsetAcmInformationTable->ChipsetACMType);
2487     if (ChipsetAcmInformationTable->ChipsetACMType < sizeof(mAcmTypeStr)/sizeof(mAcmTypeStr[0])) {
2488       printf ("    %s\n", mAcmTypeStr[ChipsetAcmInformationTable->ChipsetACMType]);
2489     }
2490     printf ("  Version                    - %02x\n", ChipsetAcmInformationTable->Version);
2491     printf ("  Length                     - %04x\n", ChipsetAcmInformationTable->Length);
2492     printf ("  ChipsetIDList              - %08x\n", ChipsetAcmInformationTable->ChipsetIDList);
2493     printf ("  OsSinitTableVer            - %08x\n", ChipsetAcmInformationTable->OsSinitTableVer);
2494     printf ("  MinMleHeaderVer            - %08x\n", ChipsetAcmInformationTable->MinMleHeaderVer);
2495     if (ChipsetAcmInformationTable->Version >= CHIPSET_ACM_INFORMATION_TABLE_VERSION_3) {
2496       printf ("  Capabilities               - %08x\n", ChipsetAcmInformationTable->Capabilities);
2497       for (Index = 0; Index < sizeof(mCapabilityStr)/sizeof(mCapabilityStr[0]); Index++) {
2498         if (mCapabilityStr[Index] == NULL) {
2499           continue;
2500         }
2501         printf (
2502           "    %s- %08x\n",
2503           mCapabilityStr[Index],
2504           (ChipsetAcmInformationTable->Capabilities & (1 << Index))
2505           );
2506       }
2507       printf ("  AcmVersion                 - %02x\n", ChipsetAcmInformationTable->AcmVersion);
2508       printf ("  AcmRevision                - %02x.%02x.%02x\n", ChipsetAcmInformationTable->AcmRevision[0], ChipsetAcmInformationTable->AcmRevision[1], ChipsetAcmInformationTable->AcmRevision[2]);
2509     }
2510     if (ChipsetAcmInformationTable->Version >= CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
2511       printf ("  ProcessorIDList            - %08x\n", ChipsetAcmInformationTable->ProcessorIDList);
2512     }
2513 
2514     ChipsetIdList = (CHIPSET_ID_LIST *)((UINTN)Acm + ChipsetAcmInformationTable->ChipsetIDList);
2515     printf ("Chipset ID List info:\n");
2516     printf ("  Count                      - %08x\n", ChipsetIdList->Count);
2517     for (Index = 0; Index < ChipsetIdList->Count; Index++) {
2518       printf ("  ID[%d]:\n", Index);
2519       printf ("    Flags                    - %08x\n", ChipsetIdList->ChipsetID[Index].Flags);
2520       printf ("      RevisionIdMask         - %08x\n", ChipsetIdList->ChipsetID[Index].Flags & ACM_CHIPSET_ID_REVISION_ID_MAKE);
2521       printf ("    VendorID                 - %04x\n", ChipsetIdList->ChipsetID[Index].VendorID);
2522       printf ("    DeviceID                 - %04x\n", ChipsetIdList->ChipsetID[Index].DeviceID);
2523       printf ("    RevisionID               - %04x\n", ChipsetIdList->ChipsetID[Index].RevisionID);
2524     }
2525     if (ChipsetAcmInformationTable->Version < CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
2526       goto End;
2527     }
2528     ProcessorIdList = (PROCESSOR_ID_LIST *)((UINTN)Acm + ChipsetAcmInformationTable->ProcessorIDList);
2529     printf ("Processor ID List info:\n");
2530     printf ("  Count                      - %08x\n", ProcessorIdList->Count);
2531     for (Index = 0; Index < ProcessorIdList->Count; Index++) {
2532       printf ("  ID[%d]:\n", Index);
2533       printf ("    FMS                      - %08x\n", ProcessorIdList->ProcessorID[Index].FMS);
2534       printf ("    FMSMask                  - %08x\n", ProcessorIdList->ProcessorID[Index].FMSMask);
2535       printf ("    PlatformID               - %016llx\n", (unsigned long long) ProcessorIdList->ProcessorID[Index].PlatformID);
2536       printf ("    PlatformMask             - %016llx\n", (unsigned long long) ProcessorIdList->ProcessorID[Index].PlatformMask);
2537     }
2538   }
2539 
2540 End:
2541   printf (
2542     "*****************************************************************************\n\n"
2543     );
2544 }
2545 
2546 BOOLEAN
CheckAcm(IN ACM_FORMAT * Acm,IN UINTN AcmMaxSize)2547 CheckAcm (
2548   IN ACM_FORMAT                        *Acm,
2549   IN UINTN                             AcmMaxSize
2550   )
2551 /*++
2552 
2553 Routine Description:
2554 
2555   Check Acm information
2556 
2557 Arguments:
2558 
2559   Acm        - ACM buffer
2560   AcmMaxSize - ACM max size
2561 
2562 Returns:
2563 
2564   TRUE  - ACM is valid
2565   FALSE - ACM is invalid
2566 
2567 --*/
2568 {
2569   CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable;
2570   CHIPSET_ID_LIST               *ChipsetIdList;
2571   PROCESSOR_ID_LIST             *ProcessorIdList;
2572   UINT8                         *Buffer;
2573 
2574   if (Acm->ModuleType != ACM_MODULE_TYPE_CHIPSET_ACM) {
2575     printf ("ACM invalid : ModuleType!\n");
2576     return FALSE;
2577   }
2578   if (Acm->Size * 4 > AcmMaxSize) {
2579     printf ("ACM invalid : Size!\n");
2580     return FALSE;
2581   }
2582 
2583   Buffer = (UINT8 *)(Acm + 1);
2584   Buffer += Acm->KeySize * 4;
2585   if (Acm->HeaderVersion == ACM_HEADER_VERSION_3) {
2586     Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE;
2587   } else {
2588     Buffer += 4;
2589     Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE;
2590   }
2591   Buffer += Acm->ScratchSize * 4;
2592 
2593   if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) == 0) {
2594     ChipsetAcmInformationTable = (CHIPSET_ACM_INFORMATION_TABLE *)Buffer;
2595     if ((UINTN)ChipsetAcmInformationTable >= (UINTN)Acm + AcmMaxSize) {
2596       printf ("ACM invalid : ChipsetAcmInformationTable!\n");
2597       return FALSE;
2598     }
2599 
2600     if (CompareGuid ((EFI_GUID *)&ChipsetAcmInformationTable->Guid, (EFI_GUID *)&mChipsetAcmInformationTableGuid03) != 0) {
2601       printf ("ACM invalid : ChipsetACMGuid!\n");
2602       return FALSE;
2603     }
2604     if (ChipsetAcmInformationTable->ChipsetACMType != CHIPSET_ACM_TYPE_BIOS) {
2605       printf ("ACM invalid : ChipsetACMType!\n");
2606       return FALSE;
2607     }
2608     if (ChipsetAcmInformationTable->Version < CHIPSET_ACM_INFORMATION_TABLE_VERSION_3) {
2609       printf ("ACM invalid : ChipsetACMVersion!\n");
2610       return FALSE;
2611     }
2612     if ((UINTN)ChipsetAcmInformationTable + ChipsetAcmInformationTable->Length > (UINTN)Acm + AcmMaxSize) {
2613       printf ("ACM invalid : ChipsetACMLength!\n");
2614       return FALSE;
2615     }
2616 
2617     if (ChipsetAcmInformationTable->ChipsetIDList >= AcmMaxSize) {
2618       printf ("ACM invalid : ChipsetACMChipsetIDList!\n");
2619       return FALSE;
2620     }
2621     ChipsetIdList = (CHIPSET_ID_LIST *)((UINTN)Acm + ChipsetAcmInformationTable->ChipsetIDList);
2622     if (ChipsetIdList->Count == 0) {
2623       printf ("ACM invalid : ChipsetACMChipsetIDListCount!\n");
2624       return FALSE;
2625     }
2626     if (ChipsetAcmInformationTable->ChipsetIDList + sizeof(CHIPSET_ID_LIST) + (ChipsetIdList->Count - 1) * sizeof(ACM_CHIPSET_ID) > AcmMaxSize) {
2627       printf ("ACM invalid : ChipsetACMChipsetIDList!\n");
2628       return FALSE;
2629     }
2630 
2631     if (ChipsetAcmInformationTable->Version < CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
2632       goto End;
2633     }
2634 
2635     if (ChipsetAcmInformationTable->ProcessorIDList >= AcmMaxSize) {
2636       printf ("ACM invalid : ChipsetACMProcessorIDList!\n");
2637       return FALSE;
2638     }
2639     ProcessorIdList = (PROCESSOR_ID_LIST *)((UINTN)Acm + ChipsetAcmInformationTable->ProcessorIDList);
2640     if (ProcessorIdList->Count == 0) {
2641       printf ("ACM invalid : ChipsetACMProcessorIdListCount!\n");
2642       return FALSE;
2643     }
2644     if (ChipsetAcmInformationTable->ChipsetIDList + sizeof(PROCESSOR_ID_LIST) + (ChipsetIdList->Count - 1) * sizeof(ACM_PROCESSOR_ID) > AcmMaxSize) {
2645       printf ("ACM invalid : ChipsetACMProcessorIdList!\n");
2646       return FALSE;
2647     }
2648   }
2649 
2650 End:
2651 
2652   return TRUE;
2653 }
2654 
2655 VOID
FillFitTable(IN UINT8 * FvBuffer,IN UINT32 FvSize,IN UINT8 * FitTableOffset)2656 FillFitTable (
2657   IN UINT8     *FvBuffer,
2658   IN UINT32    FvSize,
2659   IN UINT8     *FitTableOffset
2660   )
2661 /*++
2662 
2663 Routine Description:
2664 
2665   Fill the FIT table information to FvRecovery
2666 
2667 Arguments:
2668 
2669   FvBuffer       - FvRecovery binary buffer
2670   FvSize         - FvRecovery size
2671   FitTableOffset - The offset of FIT table in FvRecovery file
2672 
2673 Returns:
2674 
2675   None
2676 
2677 --*/
2678 {
2679   FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
2680   UINT32                          FitIndex;
2681   UINT32                          Index;
2682   UINT8                           Checksum;
2683   UINTN                           SubIndex;
2684   FIT_TABLE_CONTEXT_ENTRY         TempContextEntry;
2685   FIRMWARE_INTERFACE_TABLE_ENTRY  TempTableEntry;
2686 
2687   //
2688   // 1. FitPointer
2689   //
2690   *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) = (UINT64)(UINTN)MEMORY_TO_FLASH (FitTableOffset, FvBuffer, FvSize);
2691   if (gFitTableContext.FitTablePointerOffset2 != 0) {
2692     *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2) = (UINT64)(UINTN)MEMORY_TO_FLASH (FitTableOffset, FvBuffer, FvSize);
2693   }
2694 
2695   FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FitTableOffset;
2696   FitIndex = 0;
2697 
2698   //
2699   // 2. FitHeader
2700   //
2701   FitEntry[FitIndex].Address             = *(UINT64 *)"_FIT_   ";
2702   *(UINT32 *)&FitEntry[FitIndex].Size[0] = gFitTableContext.FitEntryNumber;
2703   FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.FitHeaderVersion;
2704   FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_HEADER;
2705   FitEntry[FitIndex].C_V                 = 1;
2706   //
2707   // Checksum will be updated later...
2708   //
2709   FitEntry[FitIndex].Checksum            = 0;
2710 
2711   //
2712   // 3. Microcode
2713   //
2714   FitIndex++;
2715   for (Index = 0; Index < gFitTableContext.MicrocodeNumber; Index++) {
2716     FitEntry[FitIndex].Address             = gFitTableContext.Microcode[Index].Address;
2717     *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0; //gFitTableContext.Microcode[Index].Size / 16;
2718     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.MicrocodeVersion;
2719     FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_MICROCODE;
2720     FitEntry[FitIndex].C_V                 = 0;
2721     FitEntry[FitIndex].Checksum            = 0;
2722     FitIndex++;
2723   }
2724 
2725   //
2726   // 4. StartupAcm
2727   //
2728   if (gFitTableContext.StartupAcm.Address != 0) {
2729     FitEntry[FitIndex].Address             = gFitTableContext.StartupAcm.Address;
2730     *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0; //gFitTableContext.StartupAcm.Size / 16;
2731     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.StartupAcmVersion;
2732     FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_STARTUP_ACM;
2733     FitEntry[FitIndex].C_V                 = 0;
2734     FitEntry[FitIndex].Checksum            = 0;
2735     FitIndex++;
2736   }
2737 
2738   //
2739   // 4.5. DiagnosticAcm
2740   //
2741   if (gFitTableContext.DiagnstAcm.Address != 0) {
2742     FitEntry[FitIndex].Address             = gFitTableContext.DiagnstAcm.Address;
2743     *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0;
2744     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.DiagnstAcmVersion;
2745     FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_DIAGNST_ACM;
2746     FitEntry[FitIndex].C_V                 = 0;
2747     FitEntry[FitIndex].Checksum            = 0;
2748     FitIndex++;
2749   }
2750   //
2751   // 5. BiosModule
2752   //
2753   //
2754   // BiosModule segments order needs to be put from low addresss to high for Btg requirement
2755   //
2756   if (gFitTableContext.BiosModuleNumber > 1) {
2757     for (Index = 0; Index < (UINTN)gFitTableContext.BiosModuleNumber - 1; Index++){
2758       for (SubIndex = 0; SubIndex < gFitTableContext.BiosModuleNumber - Index - 1; SubIndex++) {
2759         if (gFitTableContext.BiosModule[SubIndex].Address > gFitTableContext.BiosModule[SubIndex + 1].Address) {
2760           CopyMem (&TempContextEntry, &gFitTableContext.BiosModule[SubIndex], sizeof(FIT_TABLE_CONTEXT_ENTRY));
2761           CopyMem (&gFitTableContext.BiosModule[SubIndex], &gFitTableContext.BiosModule[SubIndex + 1], sizeof(FIT_TABLE_CONTEXT_ENTRY));
2762           CopyMem (&gFitTableContext.BiosModule[SubIndex + 1], &TempContextEntry, sizeof(FIT_TABLE_CONTEXT_ENTRY));
2763         }
2764       }
2765     }
2766   }
2767   for (Index = 0; Index < gFitTableContext.BiosModuleNumber; Index++) {
2768     FitEntry[FitIndex].Address             = gFitTableContext.BiosModule[Index].Address;
2769     *(UINT32 *)&FitEntry[FitIndex].Size[0] = gFitTableContext.BiosModule[Index].Size / 16;
2770     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.BiosModuleVersion;
2771     FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_BIOS_MODULE;
2772     FitEntry[FitIndex].C_V                 = 0;
2773     FitEntry[FitIndex].Checksum            = 0;
2774     FitIndex++;
2775   }
2776 
2777   //
2778   // 6. Optional module
2779   //
2780   for (Index = 0; Index < gFitTableContext.OptionalModuleNumber; Index++) {
2781     FitEntry[FitIndex].Address             = gFitTableContext.OptionalModule[Index].Address;
2782     *(UINT32 *)&FitEntry[FitIndex].Size[0] = gFitTableContext.OptionalModule[Index].Size;
2783     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.OptionalModule[Index].Version;
2784     FitEntry[FitIndex].Type                = (UINT8)gFitTableContext.OptionalModule[Index].Type;
2785     if (FitEntry[FitIndex].Type == FIT_TABLE_TYPE_CSE_SECURE_BOOT) {
2786       FitEntry[FitIndex].Rsvd              = (UINT8)gFitTableContext.OptionalModule[Index].SubType;
2787     }
2788     FitEntry[FitIndex].C_V                 = 0;
2789     FitEntry[FitIndex].Checksum            = 0;
2790     FitIndex++;
2791   }
2792 
2793   //
2794   // 7. Port module
2795   //
2796   for (Index = 0; Index < gFitTableContext.PortModuleNumber; Index++) {
2797     FitEntry[FitIndex].Address             = gFitTableContext.PortModule[Index].Address + ((UINT64)gFitTableContext.PortModule[Index].Size << 32);
2798     *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0;
2799     FitEntry[FitIndex].Version             = (UINT16)gFitTableContext.PortModule[Index].Version;
2800     FitEntry[FitIndex].Type                = (UINT8)gFitTableContext.PortModule[Index].Type;
2801     FitEntry[FitIndex].C_V                 = 0;
2802     FitEntry[FitIndex].Checksum            = 0;
2803     FitIndex++;
2804   }
2805 
2806   //
2807   // The FIT records must always be arranged in the ascending order of their type attribute in the FIT.
2808   //
2809   for (Index = 0; Index < (UINTN)FitIndex - 1; Index++){
2810     for (SubIndex = 0; SubIndex < FitIndex - Index - 1; SubIndex++) {
2811       if (FitEntry[SubIndex].Type > FitEntry[SubIndex + 1].Type) {
2812         CopyMem (&TempTableEntry, &FitEntry[SubIndex], sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
2813         CopyMem (&FitEntry[SubIndex], &FitEntry[SubIndex + 1], sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
2814         CopyMem (&FitEntry[SubIndex + 1], &TempTableEntry, sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
2815       }
2816     }
2817   }
2818 
2819   //
2820   // Update FIT header signature as final step
2821   //
2822   Checksum = CalculateChecksum8 ((UINT8 *)&FitEntry[0], sizeof (FIRMWARE_INTERFACE_TABLE_ENTRY) * FitIndex);
2823   FitEntry[0].Checksum = Checksum;
2824 }
2825 
2826 VOID
ClearFitTable(IN UINT8 * FvBuffer,IN UINT32 FvSize)2827 ClearFitTable (
2828   IN UINT8     *FvBuffer,
2829   IN UINT32    FvSize
2830   )
2831 /*++
2832 
2833 Routine Description:
2834 
2835   Clear the FIT table information to Fvrecovery
2836 
2837 Arguments:
2838 
2839   FvBuffer       - Fvrecovery binary buffer
2840   FvSize         - Fvrecovery size
2841 
2842 Returns:
2843 
2844   None
2845 
2846 --*/
2847 {
2848   FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
2849   UINT32                          EntryNum;
2850   UINT32                          FitIndex;
2851   UINT64                          FitTablePointer;
2852   UINT8                           *Buffer;
2853   UINT32                          BufferSize;
2854 
2855   FitTablePointer = *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset);
2856   FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FLASH_TO_MEMORY (FitTablePointer, FvBuffer, FvSize);
2857 
2858   //
2859   // Clear FIT pointer
2860   //
2861   *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) = 0xEEEEEEEEEEEEEEEEull;
2862   if (gFitTableContext.FitTablePointerOffset2 != 0) {
2863     *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2) = 0xEEEEEEEEEEEEEEEEull;
2864   }
2865 
2866   //
2867   // Clear FIT table
2868   //
2869   EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
2870   for (FitIndex = 0; FitIndex < EntryNum; FitIndex++) {
2871     switch (FitEntry[FitIndex].Type) {
2872     case FIT_TABLE_TYPE_BIOS_POLICY:
2873     case FIT_TABLE_TYPE_KEY_MANIFEST:
2874     case FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST:
2875     case FIT_TABLE_TYPE_BIOS_DATA_AREA:
2876     case FIT_TABLE_TYPE_CSE_SECURE_BOOT:
2877       //
2878       // Clear FIT table data buffer
2879       //
2880       Buffer = FLASH_TO_MEMORY (FitEntry[FitIndex].Address, FvBuffer, FvSize);
2881       BufferSize = (*(UINT32 *)FitEntry[FitIndex].Size) & 0xFFFFFF;
2882       SetMem (Buffer, BufferSize, 0xFF);
2883       break;
2884     default:
2885       break;
2886     }
2887     //
2888     // Clear FIT table itself
2889     //
2890     SetMem (&FitEntry[FitIndex], sizeof(FitEntry[FitIndex]), 0xFF);
2891   }
2892 }
2893 
2894 STATUS
WriteOutputFile(IN CHAR8 * FileName,IN UINT8 * FileData,IN UINT32 FileSize)2895 WriteOutputFile (
2896   IN CHAR8   *FileName,
2897   IN UINT8   *FileData,
2898   IN UINT32  FileSize
2899   )
2900 /*++
2901 
2902 Routine Description:
2903 
2904   Read input file
2905 
2906 Arguments:
2907 
2908   FileName      - The input file name
2909   FileData      - The input file data
2910   FileSize      - The input file size
2911 
2912 Returns:
2913 
2914   STATUS_SUCCESS - Write file data successfully
2915   STATUS_ERROR   - The file data is not written
2916 
2917 --*/
2918 {
2919   FILE                        *FpOut;
2920 
2921   //
2922   //Check the File Path
2923   //
2924   if (!CheckPath(FileName)) {
2925 
2926     Error (NULL, 0, 0, "File path is invalid!", NULL);
2927     return STATUS_ERROR;
2928   }
2929 
2930   //
2931   // Open the output FvRecovery.fv file
2932   //
2933   if ((FpOut = fopen (FileName, "w+b")) == NULL) {
2934     Error (NULL, 0, 0, "Unable to open file", "%s", FileName);
2935     return STATUS_ERROR;
2936   }
2937   //
2938   // Write the output FvRecovery.fv file
2939   //
2940   if ((fwrite (FileData, 1, FileSize, FpOut)) != FileSize) {
2941     Error (NULL, 0, 0, "Write output file error!", NULL);
2942     fclose (FpOut);
2943     return STATUS_ERROR;
2944   }
2945 
2946   //
2947   // Close the output FvRecovery.fv file
2948   //
2949   fclose (FpOut);
2950 
2951   return STATUS_SUCCESS;
2952 }
2953 
2954 UINT32
GetFvRecoveryInfoFromFd(IN UINT8 * FdBuffer,IN UINT32 FdFileSize,OUT UINT8 ** FvRecovery)2955 GetFvRecoveryInfoFromFd (
2956   IN UINT8                       *FdBuffer,
2957   IN UINT32                      FdFileSize,
2958   OUT UINT8                      **FvRecovery
2959   )
2960 /*++
2961 
2962 Routine Description:
2963 
2964   Get FvRecovery information from Fd file.
2965 
2966 Arguments:
2967 
2968   FdBuffer     - Fd file buffer.
2969   FdFileSize   - Fd file size.
2970   FvRecovery   - FvRecovery pointer in Fd file buffer
2971 
2972 Returns:
2973   FvRecovery file size
2974 
2975 --*/
2976 {
2977   UINT8                         *FileBuffer = NULL;
2978   UINT32                        FvRecoveryFileSize =0;
2979   EFI_GUID                      VTFGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
2980   UINT32                        FvLength;
2981   UINT32                        FileLength;
2982 
2983   *FvRecovery = NULL;
2984   FileBuffer = FindNextFvHeader (FdBuffer, FdFileSize);
2985   if (FileBuffer == NULL) {
2986     return 0;
2987   }
2988 
2989   while ((UINTN)FileBuffer < (UINTN)FdBuffer + FdFileSize) {
2990     FvLength         = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer)->FvLength;
2991 
2992     if (FindFileFromFvByGuid (FileBuffer, FvLength, &VTFGuid, &FileLength) != NULL) {
2993       //
2994       // Found the VTF
2995       //
2996       FvRecoveryFileSize = FvLength;
2997       *FvRecovery = FileBuffer;
2998     }
2999 
3000     //
3001     // Next fv
3002     //
3003     FileBuffer = (UINT8 *)FileBuffer + FvLength;
3004     if ((UINTN)FileBuffer >= (UINTN)FdBuffer + FdFileSize) {
3005       break;
3006     }
3007     FileBuffer = FindNextFvHeader (FileBuffer, (UINTN)FdBuffer + FdFileSize - (UINTN)FileBuffer);
3008     if (FileBuffer == NULL) {
3009       break;
3010     }
3011 
3012   }
3013 
3014   //
3015   // Return
3016   //
3017   return FvRecoveryFileSize;
3018 }
3019 
3020 UINT32
GetFitEntryInfo(IN UINT8 * FvBuffer,IN UINT32 FvSize)3021 GetFitEntryInfo (
3022   IN UINT8     *FvBuffer,
3023   IN UINT32    FvSize
3024   )
3025 /*++
3026 
3027 Routine Description:
3028 
3029   Fill the FIT table information to Fvrecovery
3030 
3031 Arguments:
3032 
3033   FvBuffer       - Fvrecovery binary buffer
3034   FvSize         - Fvrecovery size
3035 
3036 Returns:
3037 
3038   0 - Fit Table not found
3039 
3040 --*/
3041 {
3042   FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
3043   UINT32                          FitIndex;
3044   UINT32                          FitTableOffset;
3045 
3046   //
3047   // 1. FitPointer
3048   //
3049   if (gFitTableContext.FitTablePointerOffset == 0) {
3050     gFitTableContext.FitTablePointerOffset = DEFAULT_FIT_TABLE_POINTER_OFFSET;
3051   }
3052   gFitTableContext.FitTablePointerOffset2 = 0;
3053 
3054   FitTableOffset = *(UINT32 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset);
3055 
3056   FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FLASH_TO_MEMORY(FitTableOffset, FvBuffer, FvSize);
3057   FitIndex = 0;
3058 
3059   //
3060   // 2. FitHeader
3061   //
3062   if (FitEntry[FitIndex].Address != *(UINT64 *)"_FIT_   ") {
3063     return 0;
3064   }
3065   if (FitEntry[FitIndex].Type != FIT_TABLE_TYPE_HEADER) {
3066     return 0;
3067   }
3068   gFitTableContext.FitEntryNumber = *(UINT32 *)&FitEntry[FitIndex].Size[0];
3069   gFitTableContext.FitHeaderVersion = FitEntry[FitIndex].Version;
3070 
3071   //
3072   // 3. FitEntry
3073   //
3074   FitIndex++;
3075   for (; FitIndex < gFitTableContext.FitEntryNumber; FitIndex++) {
3076     switch (FitEntry[FitIndex].Type) {
3077     case FIT_TABLE_TYPE_MICROCODE:
3078       gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address = (UINT32)FitEntry[FitIndex].Address;
3079       gFitTableContext.MicrocodeVersion                                    = FitEntry[FitIndex].Version;
3080       gFitTableContext.MicrocodeNumber ++;
3081       break;
3082     case FIT_TABLE_TYPE_STARTUP_ACM:
3083       gFitTableContext.StartupAcm.Address = (UINT32)FitEntry[FitIndex].Address;
3084       gFitTableContext.StartupAcmVersion  = FitEntry[FitIndex].Version;
3085       break;
3086     case FIT_TABLE_TYPE_BIOS_MODULE:
3087       gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Address = (UINT32)FitEntry[FitIndex].Address;
3088       gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    = *(UINT32 *)&FitEntry[FitIndex].Size[0] * 16;
3089       gFitTableContext.BiosModuleVersion                                     = FitEntry[FitIndex].Version;
3090       gFitTableContext.BiosModuleNumber ++;
3091       break;
3092     case FIT_TABLE_TYPE_TPM_POLICY:
3093     case FIT_TABLE_TYPE_TXT_POLICY:
3094       if (FitEntry[FitIndex].Version == 0) {
3095         gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Address = (UINT32)FitEntry[FitIndex].Address;
3096         gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size    = (UINT32)(FitEntry[FitIndex].Address >> 32);
3097         gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version = FitEntry[FitIndex].Version;
3098         gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type    = FitEntry[FitIndex].Type;
3099         gFitTableContext.PortModuleNumber ++;
3100         break;
3101       }
3102       // Not Port Configure, pass through
3103     default: // Others
3104       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Address = (UINT32)FitEntry[FitIndex].Address;
3105       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Size    = *(UINT32 *)&FitEntry[FitIndex].Size[0];
3106       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Version = FitEntry[FitIndex].Version;
3107       gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber].Type    = FitEntry[FitIndex].Type;
3108       gFitTableContext.OptionalModuleNumber ++;
3109       break;
3110     }
3111   }
3112 
3113   return gFitTableContext.FitEntryNumber;
3114 }
3115 
3116 STATUS
FitGen(IN INTN argc,IN CHAR8 ** argv)3117 FitGen (
3118   IN INTN   argc,
3119   IN CHAR8  **argv
3120   )
3121 /*++
3122 
3123 Routine Description:
3124 
3125   Main function for FitGen.
3126 
3127 Arguments:
3128 
3129   argc - Number of command line parameters.
3130   argv - Array of pointers to parameter strings.
3131 
3132 Returns:
3133   STATUS_SUCCESS - Utility exits successfully.
3134   STATUS_ERROR   - Some error occurred during execution.
3135 
3136 --*/
3137 {
3138   UINT32                      FvRecoveryFileSize;
3139   UINT8                       *FileBuffer;
3140   UINT8                       *FileBufferRaw;
3141   UINTN                       FitEntryNumber;
3142   UINT8                       *FitTableOffset;
3143   STATUS                      Status;
3144   UINT32                      FitTableSize;
3145 
3146   BOOLEAN                     IsFv;
3147   UINT8                       *FdFileBuffer;
3148   UINT32                      FdFileSize;
3149 
3150   UINT8                       *AcmBuffer;
3151 
3152   FileBufferRaw = NULL;
3153   //
3154   // Step 0: Check FV or FD
3155   //
3156   if (((strcmp (argv[1], "-D") == 0) ||
3157        (strcmp (argv[1], "-d") == 0)) ) {
3158     IsFv = FALSE;
3159   } else {
3160     IsFv = TRUE;
3161   }
3162 
3163   //
3164   // Step 1: Read InputFvRecovery.fv data
3165   //
3166   if (IsFv) {
3167     Status = ReadInputFile (argv[1], &FileBuffer, &FvRecoveryFileSize, &FileBufferRaw);
3168     if (Status != STATUS_SUCCESS) {
3169       Error (NULL, 0, 0, "Unable to open file", "%s", argv[1]);
3170       goto exitFunc;
3171     }
3172     FdFileBuffer = FileBuffer;
3173     FdFileSize = FvRecoveryFileSize;
3174   } else {
3175     Status = ReadInputFile (argv[2], &FdFileBuffer, &FdFileSize, &FileBufferRaw);
3176     if (Status != STATUS_SUCCESS) {
3177       Error (NULL, 0, 0, "Unable to open file", "%s", argv[2]);
3178       goto exitFunc;
3179     }
3180 
3181     //
3182     // Get Fvrecovery information
3183     //
3184     FvRecoveryFileSize = GetFvRecoveryInfoFromFd (FdFileBuffer, FdFileSize, &FileBuffer);
3185     if ((FvRecoveryFileSize == 0) || (FileBuffer == NULL)) {
3186       Error (NULL, 0, 0, "FvRecovery not found in Fd file!", NULL);
3187       Status = STATUS_ERROR;
3188       goto exitFunc;
3189     }
3190   }
3191 
3192   //
3193   // Step 2: Calculate FIT entry number.
3194   //
3195   FitEntryNumber = GetFitEntryNumber (argc, argv, FdFileBuffer, FdFileSize);
3196   if (!gFitTableContext.Clear) {
3197     if (FitEntryNumber == 0) {
3198       Status = STATUS_ERROR;
3199       goto exitFunc;
3200     }
3201 
3202     //
3203     // For debug
3204     //
3205     PrintFitData ();
3206 
3207     //
3208     // Add 1 more FitEntry as place holder, because we need exclude FIT table itself
3209     //
3210     FitEntryNumber++;
3211 
3212     //
3213     // Step 3: Get enough space in FvRecovery.fv
3214     //
3215     FitTableOffset = GetFreeSpaceFromFv (FileBuffer, FvRecoveryFileSize, FitEntryNumber);
3216     if (FitTableOffset == NULL) {
3217       return STATUS_ERROR;
3218     }
3219     FitTableSize = FitEntryNumber * sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY);
3220     FitTableSize += FIT_ALIGNMENT;
3221     FitTableSize &= ~FIT_ALIGNMENT;
3222 
3223     CheckOverlap (
3224       MEMORY_TO_FLASH (FitTableOffset, FdFileBuffer, FdFileSize),
3225       FitTableSize
3226       );
3227 
3228     //
3229     // Get ACM buffer
3230     //
3231     if (gFitTableContext.StartupAcm.Address != 0) {
3232       AcmBuffer = FLASH_TO_MEMORY(gFitTableContext.StartupAcm.Address, FdFileBuffer, FdFileSize);
3233       if ((AcmBuffer < FdFileBuffer) || (AcmBuffer + gFitTableContext.StartupAcm.Size > FdFileBuffer + FdFileSize)) {
3234         printf ("ACM out of range - can not validate it\n");
3235         AcmBuffer = NULL;
3236       }
3237 
3238       if (AcmBuffer != NULL) {
3239         if (CheckAcm ((ACM_FORMAT *)AcmBuffer, gFitTableContext.StartupAcm.Size)) {
3240           DumpAcm ((ACM_FORMAT *)AcmBuffer);
3241         } else {
3242           Status = STATUS_ERROR;
3243           goto exitFunc;
3244         }
3245       }
3246 
3247     }
3248 
3249     //
3250     // Step 4: Fill the FIT table one by one
3251     //
3252     FillFitTable (FdFileBuffer, FdFileSize, FitTableOffset);
3253 
3254     //
3255     // For debug
3256     //
3257     PrintFitTable (FdFileBuffer, FdFileSize);
3258   } else {
3259     printf ("Clear FIT table ...\n");
3260     //
3261     // Step 3: Get FIT table info
3262     //
3263     FitEntryNumber = GetFitEntryInfo (FdFileBuffer, FdFileSize);
3264     if (FitEntryNumber == 0) {
3265       Error (NULL, 0, 0, "No FIT table found", NULL);
3266       return STATUS_ERROR;
3267     }
3268 
3269     //
3270     // For debug
3271     //
3272     PrintFitTable (FdFileBuffer, FdFileSize);
3273 
3274     //
3275     // Step 4: Clear FIT table
3276     //
3277     ClearFitTable (FdFileBuffer, FdFileSize);
3278     printf ("Clear FIT table Done!\n");
3279   }
3280 
3281   //
3282   // Step 5: Write OutputFvRecovery.fv data
3283   //
3284   if (IsFv) {
3285     Status = WriteOutputFile (argv[2], FileBuffer, FvRecoveryFileSize);
3286   } else {
3287     Status = WriteOutputFile (argv[3], FdFileBuffer, FdFileSize);
3288   }
3289 
3290 exitFunc:
3291   if (FileBufferRaw != NULL) {
3292     free ((VOID *)FileBufferRaw);
3293   }
3294   return Status;
3295 }
3296 
3297 STATUS
FitView(IN INTN argc,IN CHAR8 ** argv)3298 FitView (
3299   IN INTN   argc,
3300   IN CHAR8  **argv
3301   )
3302 /*++
3303 
3304 Routine Description:
3305 
3306   View function for FitGen.
3307 
3308 Arguments:
3309 
3310   argc - Number of command line parameters.
3311   argv - Array of pointers to parameter strings.
3312 
3313 Returns:
3314   STATUS_SUCCESS - Utility exits successfully.
3315   STATUS_ERROR   - Some error occurred during execution.
3316 
3317 --*/
3318 {
3319   UINT32                      FvRecoveryFileSize;
3320   UINT8                       *FileBuffer;
3321   UINT8                       *FileBufferRaw = NULL;
3322   STATUS                      Status;
3323 
3324   //
3325   // Step 1: Read input file
3326   //
3327   Status = ReadInputFile (argv[2], &FileBuffer, &FvRecoveryFileSize, &FileBufferRaw);
3328   if (Status != STATUS_SUCCESS) {
3329     Error (NULL, 0, 0, "Unable to open file", "%s", argv[2]);
3330     goto exitFunc;
3331   }
3332 
3333   // no -f option, use default FIT pointer offset
3334   if (argc == 3) {
3335     //
3336     // Use default address
3337     //
3338     gFitTableContext.FitTablePointerOffset = DEFAULT_FIT_TABLE_POINTER_OFFSET;
3339   } else if (stricmp (argv[3], "-f") == 0) {
3340     if (argc == 5) {
3341       //
3342       // Get offset from parameter
3343       //
3344       gFitTableContext.FitTablePointerOffset = xtoi (argv[3 + 1]);
3345     } else {
3346       Error (NULL, 0, 0, "FIT offset not specified!", NULL);
3347       goto exitFunc;
3348     }
3349   } else {
3350     Error (NULL, 0, 0, "Invalid view option: ", "%s", argv[3]);
3351     goto exitFunc;
3352   }
3353 
3354   //
3355   // For debug
3356   //
3357   PrintFitTable (FileBuffer, FvRecoveryFileSize);
3358 
3359 exitFunc:
3360   if (FileBufferRaw != NULL) {
3361     free ((VOID *)FileBufferRaw);
3362   }
3363   return Status;
3364 }
3365 
3366 int
main(int argc,char ** argv)3367 main (
3368   int   argc,
3369   char  **argv
3370   )
3371 /*++
3372 
3373 Routine Description:
3374 
3375   Main function.
3376 
3377 Arguments:
3378 
3379   argc - Number of command line parameters.
3380   argv - Array of pointers to parameter strings.
3381 
3382 Returns:
3383   STATUS_SUCCESS - Utility exits successfully.
3384   STATUS_ERROR   - Some error occurred during execution.
3385 
3386 --*/
3387 {
3388   SetUtilityName (UTILITY_NAME);
3389 
3390   //
3391   // Display utility information
3392   //
3393   PrintUtilityInfo ();
3394 
3395   //
3396   // Verify the correct number of arguments
3397   //
3398   if (argc >= MIN_VIEW_ARGS && stricmp (argv[1], "-view") == 0) {
3399     return FitView (argc, argv);
3400   } else if (argc >= MIN_ARGS) {
3401     return FitGen (argc, argv);
3402   } else {
3403     Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
3404     PrintUsage ();
3405     return STATUS_ERROR;
3406   }
3407 }
3408 
3409 unsigned int
xtoi(char * str)3410 xtoi (
3411   char  *str
3412   )
3413 /*++
3414 
3415 Routine Description:
3416 
3417   Convert hex string to uint
3418 
3419 Arguments:
3420 
3421   str  -  The string
3422 
3423 Returns:
3424 
3425 --*/
3426 {
3427   unsigned int u;
3428   char         c;
3429   unsigned int m;
3430 
3431   if (str == NULL) {
3432     return 0;
3433   }
3434 
3435   m = (unsigned int) -1 >> 4;
3436   //
3437   // skip preceeding white space
3438   //
3439   while (*str && *str == ' ') {
3440     str += 1;
3441   }
3442   //
3443   // skip preceeding zeros
3444   //
3445   while (*str && *str == '0') {
3446     str += 1;
3447   }
3448   //
3449   // skip preceeding x/X character
3450   //
3451   if (*str && (*str == 'x' || *str == 'X')) {
3452     str += 1;
3453   }
3454   //
3455   // convert hex digits
3456   //
3457   u = 0;
3458   c = *(str++);
3459   while (c) {
3460     if (c >= 'a' && c <= 'f') {
3461       c -= 'a' - 'A';
3462     }
3463 
3464     if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
3465       if (u > m) {
3466         return (unsigned int) -1;
3467       }
3468 
3469       u = (u << 4) | (c - (c >= 'A' ? 'A' - 10 : '0'));
3470     } else {
3471       //
3472       // Let application exit immediately
3473       //
3474       Error (NULL, 0, 0, "Hex value is expected!", NULL);
3475       exit (0);
3476       break;
3477     }
3478 
3479     c = *(str++);
3480   }
3481 
3482   return u;
3483 }
3484 
3485