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