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