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