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