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