]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/EfiRom/EfiRom.c
4642f441b487e8ccfce6ee84d7c0f8b628a25596
[mirror_edk2.git] / BaseTools / Source / C / EfiRom / EfiRom.c
1 /** @file
2
3 Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EfiRom.c
15
16 Abstract:
17
18 Utility program to create an EFI option ROM image from binary and
19 EFI PE32 files.
20
21 **/
22
23 #include "EfiUtilityMsgs.h"
24 #include "ParseInf.h"
25 #include "EfiRom.h"
26
27 UINT64 DebugLevel = 0;
28
29 int
30 main (
31 int Argc,
32 char *Argv[]
33 )
34 /*++
35
36 Routine Description:
37
38 Given an EFI image filename, create a ROM-able image by creating an option
39 ROM header and PCI data structure, filling them in, and then writing the
40 option ROM header + PCI data structure + EFI image out to the output file.
41
42 Arguments:
43
44 Argc - standard C main() argument count
45
46 Argv - standard C main() argument list
47
48 Returns:
49
50 0 success
51 non-zero otherwise
52
53 --*/
54 {
55 CHAR8 *Ext;
56 FILE *FptrOut;
57 UINT32 Status;
58 FILE_LIST *FList;
59 UINT32 TotalSize;
60 UINT32 Size;
61 CHAR8 *Ptr0;
62
63 SetUtilityName(UTILITY_NAME);
64
65 Status = STATUS_SUCCESS;
66 FptrOut = NULL;
67
68 //
69 // Parse the command line arguments
70 //
71 if (ParseCommandLine (Argc, Argv, &mOptions)) {
72 return STATUS_ERROR;
73 }
74
75 if (mOptions.Quiet) {
76 SetPrintLevel(40);
77 } else if (mOptions.Verbose) {
78 SetPrintLevel(15);
79 } else if (mOptions.Debug) {
80 SetPrintLevel(DebugLevel);
81 }
82
83 if (mOptions.Verbose) {
84 VerboseMsg("%s tool start.\n", UTILITY_NAME);
85 }
86
87 //
88 // If dumping an image, then do that and quit
89 //
90 if (mOptions.DumpOption == 1) {
91 if (mOptions.FileList != NULL) {
92 if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) {
93 DumpImage (mOptions.FileList);
94 goto BailOut;
95 } else {
96 Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file");
97 goto BailOut;
98 }
99 }
100 }
101 //
102 // Determine the output filename. Either what they specified on
103 // the command line, or the first input filename with a different extension.
104 //
105 if (!mOptions.OutFileName[0]) {
106 strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
107 //
108 // Find the last . on the line and replace the filename extension with
109 // the default
110 //
111 for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
112 (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
113 Ext--
114 )
115 ;
116 //
117 // If dot here, then insert extension here, otherwise append
118 //
119 if (*Ext != '.') {
120 Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
121 }
122
123 strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
124 }
125 //
126 // Make sure we don't have the same filename for input and output files
127 //
128 for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
129 if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {
130 Status = STATUS_ERROR;
131 Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);
132 goto BailOut;
133 }
134 }
135 //
136 // Now open our output file
137 //
138 if ((FptrOut = fopen (mOptions.OutFileName, "wb")) == NULL) {
139 Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);
140 goto BailOut;
141 }
142 //
143 // Process all our files
144 //
145 TotalSize = 0;
146 for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
147 Size = 0;
148 if ((FList->FileFlags & FILE_FLAG_EFI) != 0) {
149 if (mOptions.Verbose) {
150 VerboseMsg("Processing EFI file %s\n", FList->FileName);
151 }
152
153 Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
154 } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {
155 if (mOptions.Verbose) {
156 VerboseMsg("Processing binary file %s\n", FList->FileName);
157 }
158
159 Status = ProcessBinFile (FptrOut, FList, &Size);
160 } else {
161 Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName);
162 Status = STATUS_ERROR;
163 }
164
165 if (mOptions.Verbose) {
166 VerboseMsg(" Output size = 0x%X\n", (unsigned) Size);
167 }
168
169 if (Status != STATUS_SUCCESS) {
170 break;
171 }
172
173 TotalSize += Size;
174 }
175 //
176 // Check total size
177 //
178 if (TotalSize > MAX_OPTION_ROM_SIZE) {
179 Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);
180 Status = STATUS_ERROR;
181 }
182
183 BailOut:
184 if (Status == STATUS_SUCCESS) {
185 if (FptrOut != NULL) {
186 fclose (FptrOut);
187 }
188 //
189 // Clean up our file list
190 //
191 while (mOptions.FileList != NULL) {
192 FList = mOptions.FileList->Next;
193 free (mOptions.FileList);
194 mOptions.FileList = FList;
195 }
196 }
197
198 if (mOptions.Verbose) {
199 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
200 }
201
202 return GetUtilityStatus ();
203 }
204
205 static
206 int
207 ProcessBinFile (
208 FILE *OutFptr,
209 FILE_LIST *InFile,
210 UINT32 *Size
211 )
212 /*++
213
214 Routine Description:
215
216 Process a binary input file.
217
218 Arguments:
219
220 OutFptr - file pointer to output binary ROM image file we're creating
221 InFile - structure contains information on the binary file to process
222 Size - pointer to where to return the size added to the output file
223
224 Returns:
225
226 0 - successful
227
228 --*/
229 {
230 FILE *InFptr;
231 UINT32 TotalSize;
232 UINT32 FileSize;
233 UINT8 *Buffer;
234 UINT32 Status;
235 PCI_EXPANSION_ROM_HEADER *RomHdr;
236 PCI_DATA_STRUCTURE *PciDs23;
237 PCI_3_0_DATA_STRUCTURE *PciDs30;
238 UINT32 Index;
239 UINT8 ByteCheckSum;
240
241 PciDs23 = NULL;
242 PciDs30 = NULL;
243 Status = STATUS_SUCCESS;
244
245 //
246 // Try to open the input file
247 //
248 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
249 Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
250 return STATUS_ERROR;
251 }
252 //
253 // Seek to the end of the input file and get the file size. Then allocate
254 // a buffer to read it in to.
255 //
256 fseek (InFptr, 0, SEEK_END);
257 FileSize = ftell (InFptr);
258 if (mOptions.Verbose) {
259 VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize);
260 }
261
262 fseek (InFptr, 0, SEEK_SET);
263 Buffer = (UINT8 *) malloc (FileSize);
264 if (Buffer == NULL) {
265 Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!");
266 Status = STATUS_ERROR;
267 goto BailOut;
268 }
269
270 if (fread (Buffer, FileSize, 1, InFptr) != 1) {
271 Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file.");
272 Status = STATUS_ERROR;
273 goto BailOut;
274 }
275 //
276 // Total size must be an even multiple of 512 bytes, and can't exceed
277 // the option ROM image size.
278 //
279 TotalSize = FileSize;
280 if (TotalSize & 0x1FF) {
281 TotalSize = (TotalSize + 0x200) &~0x1ff;
282 }
283
284 if (TotalSize > MAX_OPTION_ROM_SIZE) {
285 Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
286 Status = STATUS_ERROR;
287 goto BailOut;
288 }
289 //
290 // Return the size to the caller so they can keep track of the running total.
291 //
292 *Size = TotalSize;
293
294 //
295 // Crude check to make sure it's a legitimate ROM image
296 //
297 RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;
298 if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
299 Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature.");
300 Status = STATUS_ERROR;
301 goto BailOut;
302 }
303 //
304 // Make sure the pointer to the PCI data structure is within the size of the image.
305 // Then check it for valid signature.
306 //
307 if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
308 Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset.");
309 Status = STATUS_ERROR;
310 goto BailOut;
311 }
312
313 //
314 // Check the header is conform to PCI2.3 or PCI3.0
315 //
316 if (mOptions.Pci23 == 1) {
317 PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
318 if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
319 Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
320 Status = STATUS_ERROR;
321 goto BailOut;
322 }
323 } else {
324 //
325 // Default setting is PCI3.0 header
326 //
327 PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset);
328 if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
329 Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
330 Status = STATUS_ERROR;
331 goto BailOut;
332 }
333 }
334
335 //
336 // ReSet Option Rom size
337 //
338 if (mOptions.Pci23 == 1) {
339 PciDs23->ImageLength = (UINT16) (TotalSize / 512);
340 } else {
341 PciDs30->ImageLength = (UINT16) (TotalSize / 512);
342 }
343
344 //
345 // If this is the last image, then set the LAST bit unless requested not
346 // to via the command-line -n argument. Otherwise, make sure you clear it.
347 //
348 if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
349 if (mOptions.Pci23 == 1) {
350 PciDs23->Indicator = INDICATOR_LAST;
351 } else {
352 PciDs30->Indicator = INDICATOR_LAST;
353 }
354 } else {
355 if (mOptions.Pci23 == 1) {
356 PciDs23->Indicator = 0;
357 } else {
358 PciDs30->Indicator = 0;
359 }
360 }
361
362 ByteCheckSum = 0;
363 for (Index = 0; Index < FileSize - 1; Index++) {
364 ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
365 }
366
367 Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
368 if (mOptions.Verbose) {
369 VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]);
370 }
371
372 //
373 // Now copy the input file contents out to the output file
374 //
375 if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
376 Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL);
377 Status = STATUS_ERROR;
378 goto BailOut;
379 }
380
381 TotalSize -= FileSize;
382 //
383 // Pad the rest of the image to make it a multiple of 512 bytes
384 //
385 while (TotalSize > 0) {
386 putc (~0, OutFptr);
387 TotalSize--;
388 }
389
390 BailOut:
391 if (InFptr != NULL) {
392 fclose (InFptr);
393 }
394
395 if (Buffer != NULL) {
396 free (Buffer);
397 }
398 //
399 // Print the file name if errors occurred
400 //
401 if (Status != STATUS_SUCCESS) {
402 Error (NULL, 0, 0003, "Error", "Error parsing file: %s", InFile->FileName);
403 }
404
405 return Status;
406 }
407
408 static
409 int
410 ProcessEfiFile (
411 FILE *OutFptr,
412 FILE_LIST *InFile,
413 UINT16 VendId,
414 UINT16 DevId,
415 UINT32 *Size
416 )
417 /*++
418
419 Routine Description:
420
421 Process a PE32 EFI file.
422
423 Arguments:
424
425 OutFptr - file pointer to output binary ROM image file we're creating
426 InFile - structure contains information on the PE32 file to process
427 VendId - vendor ID as required in the option ROM header
428 DevId - device ID as required in the option ROM header
429 Size - pointer to where to return the size added to the output file
430
431 Returns:
432
433 0 - successful
434
435 --*/
436 {
437 UINT32 Status;
438 FILE *InFptr;
439 EFI_PCI_EXPANSION_ROM_HEADER RomHdr;
440 PCI_DATA_STRUCTURE PciDs23;
441 PCI_3_0_DATA_STRUCTURE PciDs30;
442 UINT32 FileSize;
443 UINT32 CompressedFileSize;
444 UINT8 *Buffer;
445 UINT8 *CompressedBuffer;
446 UINT8 *TempBufferPtr;
447 UINT32 TotalSize;
448 UINT32 HeaderSize;
449 UINT16 MachineType;
450 UINT16 SubSystem;
451 UINT32 HeaderPadBytes;
452
453 //
454 // Try to open the input file
455 //
456 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
457 Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);
458 return STATUS_ERROR;
459 }
460 //
461 // Initialize our buffer pointers to null.
462 //
463 Buffer = NULL;
464 CompressedBuffer = NULL;
465
466 //
467 // Double-check the file to make sure it's what we expect it to be
468 //
469 Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
470 if (Status != STATUS_SUCCESS) {
471 goto BailOut;
472 }
473 //
474 // Seek to the end of the input file and get the file size
475 //
476 fseek (InFptr, 0, SEEK_END);
477 FileSize = ftell (InFptr);
478
479 //
480 // Get the size of the headers we're going to put in front of the image. The
481 // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
482 //
483 if (sizeof (RomHdr) & 0x03) {
484 HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
485 } else {
486 HeaderPadBytes = 0;
487 }
488
489 //
490 // For Pci3.0 to use the different data structure.
491 //
492 if (mOptions.Pci23 == 1) {
493 HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
494 } else {
495 HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
496 }
497
498 if (mOptions.Verbose) {
499 VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize);
500 }
501 //
502 // Allocate memory for the entire file (in case we have to compress), then
503 // seek back to the beginning of the file and read it into our buffer.
504 //
505 Buffer = (UINT8 *) malloc (FileSize);
506 if (Buffer == NULL) {
507 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
508 Status = STATUS_ERROR;
509 goto BailOut;
510 }
511
512 fseek (InFptr, 0, SEEK_SET);
513 if (fread (Buffer, FileSize, 1, InFptr) != 1) {
514 Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName);
515 Status = STATUS_ERROR;
516 goto BailOut;
517 }
518 //
519 // Now determine the size of the final output file. It's either the header size
520 // plus the file's size, or the header size plus the compressed file size.
521 //
522 if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
523 //
524 // Allocate a buffer into which we can compress the image, compress it,
525 // and use that size as the new size.
526 //
527 CompressedBuffer = (UINT8 *) malloc (FileSize);
528 if (CompressedBuffer == NULL) {
529 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
530 Status = STATUS_ERROR;
531 goto BailOut;
532 }
533
534 CompressedFileSize = FileSize;
535 Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
536 if (Status != STATUS_SUCCESS) {
537 Error (NULL, 0, 0007, "Error compressing file!", NULL);
538 goto BailOut;
539 }
540 //
541 // Now compute the size, then swap buffer pointers.
542 //
543 if (mOptions.Verbose) {
544 VerboseMsg(" Comp size = 0x%X\n", (unsigned) CompressedFileSize);
545 }
546
547 TotalSize = CompressedFileSize + HeaderSize;
548 FileSize = CompressedFileSize;
549 TempBufferPtr = Buffer;
550 Buffer = CompressedBuffer;
551 CompressedBuffer = TempBufferPtr;
552 } else {
553 TotalSize = FileSize + HeaderSize;
554 }
555 //
556 // Total size must be an even multiple of 512 bytes
557 //
558 if (TotalSize & 0x1FF) {
559 TotalSize = (TotalSize + 0x200) &~0x1ff;
560 }
561 //
562 // Check size
563 //
564 if (TotalSize > MAX_OPTION_ROM_SIZE) {
565 Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
566 Status = STATUS_ERROR;
567 goto BailOut;
568 }
569 //
570 // Return the size to the caller so they can keep track of the running total.
571 //
572 *Size = TotalSize;
573
574 //
575 // Now fill in the ROM header. These values come from chapter 18 of the
576 // EFI 1.02 specification.
577 //
578 memset (&RomHdr, 0, sizeof (RomHdr));
579 RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
580 RomHdr.InitializationSize = (UINT16) (TotalSize / 512);
581 RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
582 RomHdr.EfiSubsystem = SubSystem;
583 RomHdr.EfiMachineType = MachineType;
584 RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;
585 RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);
586 //
587 // Set image as compressed or not
588 //
589 if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
590 RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
591 }
592 //
593 // Fill in the PCI data structure
594 //
595 if (mOptions.Pci23 == 1) {
596 memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE));
597 } else {
598 memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE));
599 }
600
601 if (mOptions.Pci23 == 1) {
602 PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
603 PciDs23.VendorId = VendId;
604 PciDs23.DeviceId = DevId;
605 PciDs23.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE);
606 PciDs23.Revision = 0;
607 //
608 // Class code and code revision from the command line (optional)
609 //
610 PciDs23.ClassCode[0] = (UINT8) InFile->ClassCode;
611 PciDs23.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
612 PciDs23.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
613 PciDs23.ImageLength = RomHdr.InitializationSize;
614 PciDs23.CodeRevision = InFile->CodeRevision;
615 PciDs23.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
616 } else {
617 PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
618 PciDs30.VendorId = VendId;
619 PciDs30.DeviceId = DevId;
620 PciDs30.DeviceListOffset = 0; // to be fixed
621 PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
622 PciDs30.Revision = 0x3;
623 //
624 // Class code and code revision from the command line (optional)
625 //
626 PciDs30.ClassCode[0] = (UINT8) InFile->ClassCode;
627 PciDs30.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
628 PciDs30.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
629 PciDs30.ImageLength = RomHdr.InitializationSize;
630 PciDs30.CodeRevision = InFile->CodeRevision;
631 PciDs30.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
632 PciDs30.MaxRuntimeImageLength = 0; // to be fixed
633 PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed
634 PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed
635 }
636 //
637 // If this is the last image, then set the LAST bit unless requested not
638 // to via the command-line -n argument.
639 //
640 if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
641 if (mOptions.Pci23 == 1) {
642 PciDs23.Indicator = INDICATOR_LAST;
643 } else {
644 PciDs30.Indicator = INDICATOR_LAST;}
645 } else {
646 if (mOptions.Pci23 == 1) {
647 PciDs23.Indicator = 0;
648 } else {
649 PciDs30.Indicator = 0;
650 }
651 }
652 //
653 // Write the ROM header to the output file
654 //
655 if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
656 Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL);
657 Status = STATUS_ERROR;
658 goto BailOut;
659 }
660
661 //
662 // Write pad bytes to align the PciDs
663 //
664 while (HeaderPadBytes > 0) {
665 if (putc (0, OutFptr) == EOF) {
666 Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL);
667 Status = STATUS_ERROR;
668 goto BailOut;
669 }
670
671 HeaderPadBytes--;
672 }
673 //
674 // Write the PCI data structure header to the output file
675 //
676 if (mOptions.Pci23 == 1) {
677 if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) {
678 Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
679 Status = STATUS_ERROR;
680 goto BailOut;
681 }
682 } else {
683 if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {
684 Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
685 Status = STATUS_ERROR;
686 goto BailOut;
687 }
688 }
689 //
690 // Keep track of how many bytes left to write
691 //
692 TotalSize -= HeaderSize;
693
694 //
695 // Now dump the input file's contents to the output file
696 //
697 if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
698 Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL);
699 Status = STATUS_ERROR;
700 goto BailOut;
701 }
702
703 TotalSize -= FileSize;
704 //
705 // Pad the rest of the image to make it a multiple of 512 bytes
706 //
707 while (TotalSize > 0) {
708 if (putc (~0, OutFptr) == EOF) {
709 Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
710 Status = STATUS_ERROR;
711 goto BailOut;
712 }
713
714 TotalSize--;
715 }
716
717 BailOut:
718 if (InFptr != NULL) {
719 fclose (InFptr);
720 }
721 //
722 // Free up our buffers
723 //
724 if (Buffer != NULL) {
725 free (Buffer);
726 }
727
728 if (CompressedBuffer != NULL) {
729 free (CompressedBuffer);
730 }
731 //
732 // Print the file name if errors occurred
733 //
734 if (Status != STATUS_SUCCESS) {
735 Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName);
736 }
737
738 return Status;
739 }
740
741 static
742 int
743 CheckPE32File (
744 FILE *Fptr,
745 UINT16 *MachineType,
746 UINT16 *SubSystem
747 )
748 /*++
749
750 Routine Description:
751
752 Given a file pointer to a supposed PE32 image file, verify that it is indeed a
753 PE32 image file, and then return the machine type in the supplied pointer.
754
755 Arguments:
756
757 Fptr File pointer to the already-opened PE32 file
758 MachineType Location to stuff the machine type of the PE32 file. This is needed
759 because the image may be Itanium-based, IA32, or EBC.
760
761 Returns:
762
763 0 success
764 non-zero otherwise
765
766 --*/
767 {
768 EFI_IMAGE_DOS_HEADER DosHeader;
769 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;
770
771 //
772 // Position to the start of the file
773 //
774 fseek (Fptr, 0, SEEK_SET);
775
776 //
777 // Read the DOS header
778 //
779 if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
780 Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL);
781 return STATUS_ERROR;
782 }
783 //
784 // Check the magic number (0x5A4D)
785 //
786 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
787 Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!");
788 return STATUS_ERROR;
789 }
790 //
791 // Position into the file and check the PE signature
792 //
793 fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
794
795 //
796 // Read PE headers
797 //
798 if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) {
799 Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL);
800 return STATUS_ERROR;
801 }
802
803
804 //
805 // Check the PE signature in the header "PE\0\0"
806 //
807 if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
808 Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!");
809 return STATUS_ERROR;
810 }
811
812 memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2);
813
814 if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
815 *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem;
816 } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
817 *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;
818 } else {
819 Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!");
820 return STATUS_ERROR;
821 }
822
823 if (mOptions.Verbose) {
824 VerboseMsg(" Got subsystem = 0x%X from image\n", *SubSystem);
825 }
826
827 //
828 // File was successfully identified as a PE32
829 //
830 return STATUS_SUCCESS;
831 }
832
833 static
834 int
835 ParseCommandLine (
836 int Argc,
837 char *Argv[],
838 OPTIONS *Options
839 )
840 /*++
841
842 Routine Description:
843
844 Given the Argc/Argv program arguments, and a pointer to an options structure,
845 parse the command-line options and check their validity.
846
847
848 Arguments:
849
850 Argc - standard C main() argument count
851 Argv[] - standard C main() argument list
852 Options - pointer to a structure to store the options in
853
854 Returns:
855
856 STATUS_SUCCESS success
857 non-zero otherwise
858
859 --*/
860 {
861 FILE_LIST *FileList;
862 FILE_LIST *PrevFileList;
863 UINT32 FileFlags;
864 UINT32 ClassCode;
865 UINT32 CodeRevision;
866 EFI_STATUS Status;
867 BOOLEAN EfiRomFlag;
868 UINT64 TempValue;
869
870 FileFlags = 0;
871 EfiRomFlag = FALSE;
872
873 //
874 // Clear out the options
875 //
876 memset ((char *) Options, 0, sizeof (OPTIONS));
877
878 //
879 // To avoid compile warnings
880 //
881 FileList = PrevFileList = NULL;
882
883 ClassCode = 0;
884 CodeRevision = 0;
885 //
886 // Skip over the program name
887 //
888 Argc--;
889 Argv++;
890
891 //
892 // If no arguments, assume they want usage info
893 //
894 if (Argc == 0) {
895 Usage ();
896 return STATUS_ERROR;
897 }
898
899 if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {
900 Usage();
901 return STATUS_ERROR;
902 }
903
904 if ((stricmp(Argv[0], "--version") == 0)) {
905 Version();
906 return STATUS_ERROR;
907 }
908
909 //
910 // Process until no more arguments
911 //
912 while (Argc > 0) {
913 if (Argv[0][0] == '-') {
914 //
915 // Vendor ID specified with -f
916 //
917 if (stricmp (Argv[0], "-f") == 0) {
918 //
919 // Make sure there's another parameter
920 //
921 Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
922 if (EFI_ERROR (Status)) {
923 Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
924 return 1;
925 }
926 if (TempValue >= 0x10000) {
927 Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);
928 return 1;
929 }
930 Options->VendId = (UINT16) TempValue;
931 Options->VendIdValid = 1;
932
933 Argv++;
934 Argc--;
935 } else if (stricmp (Argv[0], "-i") == 0) {
936 //
937 // Device ID specified with -i
938 // Make sure there's another parameter
939 //
940 Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
941 if (EFI_ERROR (Status)) {
942 Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
943 return 1;
944 }
945 if (TempValue >= 0x10000) {
946 Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);
947 return 1;
948 }
949 Options->DevId = (UINT16) TempValue;
950 Options->DevIdValid = 1;
951
952 Argv++;
953 Argc--;
954 } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {
955 //
956 // Output filename specified with -o
957 // Make sure there's another parameter
958 //
959 if (Argv[1] == NULL || Argv[1][0] == '-') {
960 Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);
961 return STATUS_ERROR;
962 }
963 strcpy (Options->OutFileName, Argv[1]);
964
965 Argv++;
966 Argc--;
967 } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) {
968 //
969 // Help option
970 //
971 Usage ();
972 return STATUS_ERROR;
973 } else if (stricmp (Argv[0], "-b") == 0) {
974 //
975 // Specify binary files with -b
976 //
977 FileFlags = FILE_FLAG_BINARY;
978 } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
979 //
980 // Specify EFI files with -e. Specify EFI-compressed with -c.
981 //
982 FileFlags = FILE_FLAG_EFI;
983 if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {
984 FileFlags |= FILE_FLAG_COMPRESS;
985 }
986 //
987 // Specify not to set the LAST bit in the last file with -n
988 //
989 } else if (stricmp (Argv[0], "-n") == 0) {
990 Options->NoLast = 1;
991 } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) {
992 //
993 // -v for verbose
994 //
995 Options->Verbose = 1;
996 } else if (stricmp (Argv[0], "--debug") == 0) {
997 Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);
998 if (EFI_ERROR (Status)) {
999 Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
1000 return 1;
1001 }
1002 if (DebugLevel > 9) {
1003 Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);
1004 return 1;
1005 }
1006 if (DebugLevel>=5 && DebugLevel<=9) {
1007 Options->Debug = TRUE;
1008 } else {
1009 Options->Debug = FALSE;
1010 }
1011 Argv++;
1012 Argc--;
1013 } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) {
1014 Options->Quiet = TRUE;
1015 } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 0)) {
1016 //
1017 // -dump for dumping a ROM image. In this case, say that the device id
1018 // and vendor id are valid so we don't have to specify bogus ones on the
1019 // command line.
1020 //
1021 Options->DumpOption = 1;
1022
1023 Options->VendIdValid = 1;
1024 Options->DevIdValid = 1;
1025 FileFlags = FILE_FLAG_BINARY;
1026 } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {
1027 //
1028 // Class code value for the next file in the list.
1029 // Make sure there's another parameter
1030 //
1031 Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
1032 if (EFI_ERROR (Status)) {
1033 Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
1034 return 1;
1035 }
1036 ClassCode = (UINT32) TempValue;
1037 if (ClassCode & 0xFF000000) {
1038 Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);
1039 return STATUS_ERROR;
1040 }
1041 if (FileList != NULL && FileList->ClassCode == 0) {
1042 FileList->ClassCode = ClassCode;
1043 }
1044 Argv++;
1045 Argc--;
1046 } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) {
1047 //
1048 // Code revision in the PCI data structure. The value is for the next
1049 // file in the list.
1050 // Make sure there's another parameter
1051 //
1052 Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
1053 if (EFI_ERROR (Status)) {
1054 Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
1055 return 1;
1056 }
1057 CodeRevision = (UINT32) TempValue;
1058 if (CodeRevision & 0xFFFF0000) {
1059 Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);
1060 return STATUS_ERROR;
1061 }
1062 if (FileList != NULL && FileList->CodeRevision == 0) {
1063 FileList->CodeRevision = (UINT16) CodeRevision;
1064 }
1065 Argv++;
1066 Argc--;
1067 } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) {
1068 //
1069 // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout.
1070 //
1071 mOptions.Pci23 = 1;
1072 } else {
1073 Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);
1074 return STATUS_ERROR;
1075 }
1076 } else {
1077 //
1078 // Not a slash-option argument. Must be a file name. Make sure they've specified
1079 // -e or -b already.
1080 //
1081 if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {
1082 Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);
1083 return STATUS_ERROR;
1084 }
1085 //
1086 // Check Efi Option RomImage
1087 //
1088 if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) {
1089 EfiRomFlag = TRUE;
1090 }
1091 //
1092 // Create a new file structure
1093 //
1094 FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
1095 if (FileList == NULL) {
1096 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
1097 return STATUS_ERROR;
1098 }
1099
1100 //
1101 // set flag and class code for this image.
1102 //
1103 memset ((char *) FileList, 0, sizeof (FILE_LIST));
1104 FileList->FileName = Argv[0];
1105 FileList->FileFlags = FileFlags;
1106 FileList->ClassCode = ClassCode;
1107 FileList->CodeRevision = (UINT16) CodeRevision;
1108 ClassCode = 0;
1109 CodeRevision = 0;
1110
1111 if (Options->FileList == NULL) {
1112 Options->FileList = FileList;
1113 } else {
1114 if (PrevFileList == NULL) {
1115 PrevFileList = FileList;
1116 } else {
1117 PrevFileList->Next = FileList;
1118 }
1119 }
1120
1121 PrevFileList = FileList;
1122 }
1123 //
1124 // Next argument
1125 //
1126 Argv++;
1127 Argc--;
1128 }
1129
1130 //
1131 // Must have specified some files
1132 //
1133 if (Options->FileList == NULL) {
1134 Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");
1135 return STATUS_ERROR;
1136 }
1137
1138 //
1139 // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified.
1140 //
1141 if (EfiRomFlag) {
1142 if (!Options->VendIdValid) {
1143 Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);
1144 return STATUS_ERROR;
1145 }
1146
1147 if (!Options->DevIdValid) {
1148 Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);
1149 return STATUS_ERROR;
1150 }
1151 }
1152
1153 return 0;
1154 }
1155
1156 static
1157 void
1158 Version (
1159 VOID
1160 )
1161 /*++
1162
1163 Routine Description:
1164
1165 Print version information for this utility.
1166
1167 Arguments:
1168
1169 None.
1170
1171 Returns:
1172
1173 Nothing.
1174 --*/
1175 {
1176 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
1177 }
1178
1179 static
1180 void
1181 Usage (
1182 VOID
1183 )
1184 /*++
1185
1186 Routine Description:
1187
1188 Print usage information for this utility.
1189
1190 Arguments:
1191
1192 None.
1193
1194 Returns:
1195
1196 Nothing.
1197
1198 --*/
1199 {
1200 //
1201 // Summary usage
1202 //
1203 fprintf (stdout, "Usage: %s [options] [file name<s>] \n\n", UTILITY_NAME);
1204
1205 //
1206 // Copyright declaration
1207 //
1208 fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
1209
1210 //
1211 // Details Option
1212 //
1213 fprintf (stdout, "Options:\n");
1214 fprintf (stdout, " -o FileName, --output FileName\n\
1215 File will be created to store the ouput content.\n");
1216 fprintf (stdout, " -e EfiFileName\n\
1217 EFI PE32 image files.\n");
1218 fprintf (stdout, " -ec EfiFileName\n\
1219 EFI PE32 image files and will be compressed.\n");
1220 fprintf (stdout, " -b BinFileName\n\
1221 Legacy binary files.\n");
1222 fprintf (stdout, " -l ClassCode\n\
1223 Hex ClassCode in the PCI data structure header.\n");
1224 fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n");
1225 fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n");
1226 fprintf (stdout, " -f VendorId\n\
1227 Hex PCI Vendor ID for the device OpROM.\n");
1228 fprintf (stdout, " -i DeviceId\n\
1229 Hex PCI Device ID for the device OpROM.\n");
1230 fprintf (stdout, " -p, --pci23\n\
1231 Default layout meets PCI 3.0 specifications\n\
1232 specifying this flag will for a PCI 2.3 layout.\n");
1233 fprintf (stdout, " -d, --dump\n\
1234 Dump the headers of an existing option ROM image.\n");
1235 fprintf (stdout, " -v, --verbose\n\
1236 Turn on verbose output with informational messages.\n");
1237 fprintf (stdout, " --version Show program's version number and exit.\n");
1238 fprintf (stdout, " -h, --help\n\
1239 Show this help message and exit.\n");
1240 fprintf (stdout, " -q, --quiet\n\
1241 Disable all messages except FATAL ERRORS.\n");
1242 fprintf (stdout, " --debug [#,0-9]\n\
1243 Enable debug messages at level #.\n");
1244 }
1245
1246 static
1247 void
1248 DumpImage (
1249 FILE_LIST *InFile
1250 )
1251 /*++
1252
1253 Routine Description:
1254
1255 Dump the headers of an existing option ROM image
1256
1257 Arguments:
1258
1259 InFile - the file name of an existing option ROM image
1260
1261 Returns:
1262
1263 none
1264
1265 --*/
1266 {
1267 PCI_EXPANSION_ROM_HEADER PciRomHdr;
1268 FILE *InFptr;
1269 UINT32 ImageStart;
1270 UINT32 ImageCount;
1271 EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;
1272 PCI_DATA_STRUCTURE PciDs23;
1273 PCI_3_0_DATA_STRUCTURE PciDs30;
1274
1275 //
1276 // Open the input file
1277 //
1278 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
1279 Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
1280 return ;
1281 }
1282 //
1283 // Go through the image and dump the header stuff for each
1284 //
1285 ImageCount = 0;
1286 for (;;) {
1287 //
1288 // Save our postition in the file, since offsets in the headers
1289 // are relative to the particular image.
1290 //
1291 ImageStart = ftell (InFptr);
1292 ImageCount++;
1293
1294 //
1295 // Read the option ROM header. Have to assume a raw binary image for now.
1296 //
1297 if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {
1298 Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!");
1299 goto BailOut;
1300 }
1301
1302 //
1303 // Dump the contents of the header
1304 //
1305 fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart);
1306 fprintf (stdout, " ROM header contents\n");
1307 fprintf (stdout, " Signature 0x%04X\n", PciRomHdr.Signature);
1308 fprintf (stdout, " PCIR offset 0x%04X\n", PciRomHdr.PcirOffset);
1309 //
1310 // Find PCI data structure
1311 //
1312 if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
1313 Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!");
1314 goto BailOut;
1315 }
1316 //
1317 // Read and dump the PCI data structure
1318 //
1319 memset (&PciDs23, 0, sizeof (PciDs23));
1320 memset (&PciDs30, 0, sizeof (PciDs30));
1321 if (mOptions.Pci23 == 1) {
1322 if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) {
1323 Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
1324 goto BailOut;
1325 }
1326 } else {
1327 if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) {
1328 Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
1329 goto BailOut;
1330 }
1331 }
1332 if (mOptions.Verbose) {
1333 VerboseMsg("Read PCI data structure from file %s", InFile->FileName);
1334 }
1335
1336 //fprintf (stdout, " PCI Data Structure\n");
1337 if (mOptions.Pci23 == 1) {
1338 fprintf (
1339 stdout,
1340 " Signature %c%c%c%c\n",
1341 (char) PciDs23.Signature,
1342 (char) (PciDs23.Signature >> 8),
1343 (char) (PciDs23.Signature >> 16),
1344 (char) (PciDs23.Signature >> 24)
1345 );
1346 fprintf (stdout, " Vendor ID 0x%04X\n", PciDs23.VendorId);
1347 fprintf (stdout, " Device ID 0x%04X\n", PciDs23.DeviceId);
1348 fprintf (stdout, " Length 0x%04X\n", PciDs23.Length);
1349 fprintf (stdout, " Revision 0x%04X\n", PciDs23.Revision);
1350 fprintf (
1351 stdout,
1352 " Class Code 0x%06X\n",
1353 (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16))
1354 );
1355 fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs23.ImageLength * 512);
1356 fprintf (stdout, " Code revision: 0x%04X\n", PciDs23.CodeRevision);
1357 fprintf (stdout, " Indicator 0x%02X", PciDs23.Indicator);
1358 } else {
1359 fprintf (
1360 stdout,
1361 " Signature %c%c%c%c\n",
1362 (char) PciDs30.Signature,
1363 (char) (PciDs30.Signature >> 8),
1364 (char) (PciDs30.Signature >> 16),
1365 (char) (PciDs30.Signature >> 24)
1366 );
1367 fprintf (stdout, " Vendor ID 0x%04X\n", PciDs30.VendorId);
1368 fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId);
1369 fprintf (stdout, " Length 0x%04X\n", PciDs30.Length);
1370 fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision);
1371 fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset);
1372 fprintf (
1373 stdout,
1374 " Class Code 0x%06X\n",
1375 (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16))
1376 );
1377 fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs30.ImageLength * 512);
1378 fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision);
1379 fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", PciDs30.MaxRuntimeImageLength);
1380 fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);
1381 fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);
1382 fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator);
1383 }
1384 //
1385 // Print the indicator, used to flag the last image
1386 //
1387 if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
1388 fprintf (stdout, " (last image)\n");
1389 } else {
1390 fprintf (stdout, "\n");
1391 }
1392 //
1393 // Print the code type. If EFI code, then we can provide more info.
1394 //
1395 if (mOptions.Pci23 == 1) {
1396 fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType);
1397 } else {
1398 fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType);
1399 }
1400 if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
1401 fprintf (stdout, " (EFI image)\n");
1402 //
1403 // Re-read the header as an EFI ROM header, then dump more info
1404 //
1405 fprintf (stdout, " EFI ROM header contents\n");
1406 if (fseek (InFptr, ImageStart, SEEK_SET)) {
1407 Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL);
1408 goto BailOut;
1409 }
1410
1411 if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
1412 Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL);
1413 goto BailOut;
1414 }
1415 //
1416 // Now dump more info
1417 //
1418 fprintf (stdout, " EFI Signature 0x%04X\n", (unsigned) EfiRomHdr.EfiSignature);
1419 fprintf (
1420 stdout,
1421 " Compression Type 0x%04X ",
1422 EfiRomHdr.CompressionType
1423 );
1424 if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
1425 fprintf (stdout, "(compressed)\n");
1426 } else {
1427 fprintf (stdout, "(not compressed)\n");
1428 }
1429
1430 fprintf (
1431 stdout,
1432 " Machine type 0x%04X (%s)\n",
1433 EfiRomHdr.EfiMachineType,
1434 GetMachineTypeStr (EfiRomHdr.EfiMachineType)
1435 );
1436 fprintf (
1437 stdout,
1438 " Subsystem 0x%04X (%s)\n",
1439 EfiRomHdr.EfiSubsystem,
1440 GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)
1441 );
1442 fprintf (
1443 stdout,
1444 " EFI image offset 0x%04X (@0x%X)\n",
1445 EfiRomHdr.EfiImageHeaderOffset,
1446 EfiRomHdr.EfiImageHeaderOffset + (unsigned) ImageStart
1447 );
1448
1449 } else {
1450 //
1451 // Not an EFI image
1452 //
1453 fprintf (stdout, "\n");
1454 }
1455 //
1456 // If code type is EFI image, then dump it as well?
1457 //
1458 // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
1459 // }
1460 //
1461 // If last image, then we're done
1462 //
1463 if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
1464 goto BailOut;
1465 }
1466 //
1467 // Seek to the start of the next image
1468 //
1469 if (mOptions.Pci23 == 1) {
1470 if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) {
1471 Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
1472 goto BailOut;
1473 }
1474 } else {
1475 if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) {
1476 Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
1477 goto BailOut;
1478 }
1479 }
1480 }
1481
1482 BailOut:
1483 fclose (InFptr);
1484 }
1485
1486 char *
1487 GetMachineTypeStr (
1488 UINT16 MachineType
1489 )
1490 /*++
1491
1492 Routine Description:
1493
1494 GC_TODO: Add function description
1495
1496 Arguments:
1497
1498 MachineType - GC_TODO: add argument description
1499
1500 Returns:
1501
1502 GC_TODO: add return values
1503
1504 --*/
1505 {
1506 int Index;
1507
1508 for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
1509 if (mMachineTypes[Index].Value == MachineType) {
1510 return mMachineTypes[Index].Name;
1511 }
1512 }
1513
1514 return "unknown";
1515 }
1516
1517 static
1518 char *
1519 GetSubsystemTypeStr (
1520 UINT16 SubsystemType
1521 )
1522 /*++
1523
1524 Routine Description:
1525
1526 GC_TODO: Add function description
1527
1528 Arguments:
1529
1530 SubsystemType - GC_TODO: add argument description
1531
1532 Returns:
1533
1534 GC_TODO: add return values
1535
1536 --*/
1537 {
1538 int Index;
1539
1540 for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
1541 if (mSubsystemTypes[Index].Value == SubsystemType) {
1542 return mSubsystemTypes[Index].Name;
1543 }
1544 }
1545
1546 return "unknown";
1547 }