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