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