]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
Update all the code to consume the ConvertDevicePathToText, ConvertDevicePathNodeToTe...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciOptionRomSupport.c
CommitLineData
9060e3ec 1/** @file\r
2 PCI Rom supporting funtions implementation for PCI Bus module.\r
3\r
94020bb4 4Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
9060e3ec 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PciBus.h"\r
16\r
17/**\r
18 Load the EFI Image from Option ROM\r
19\r
20 @param PciIoDevice PCI IO device instance.\r
21 @param FilePath The file path of the EFI Image\r
22 @param BufferSize On input the size of Buffer in bytes. On output with a return\r
23 code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
24 On output with a return code of EFI_BUFFER_TOO_SMALL,\r
25 the size of Buffer required to retrieve the requested file.\r
26 @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,\r
27 then no the size of the requested file is returned in BufferSize.\r
28\r
29 @retval EFI_SUCCESS The file was loaded.\r
30 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
31 BufferSize is NULL.\r
32 @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.\r
33 @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.\r
34 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
35 BufferSize has been updated with the size needed to complete the request.\r
36**/\r
37EFI_STATUS\r
38LocalLoadFile2 (\r
39 IN PCI_IO_DEVICE *PciIoDevice,\r
40 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
41 IN OUT UINTN *BufferSize,\r
42 IN VOID *Buffer OPTIONAL\r
43 )\r
44{\r
45 EFI_STATUS Status;\r
46 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *EfiOpRomImageNode;\r
47 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
48 PCI_DATA_STRUCTURE *Pcir;\r
49 UINT32 ImageSize;\r
50 UINT8 *ImageBuffer;\r
51 UINT32 ImageLength;\r
52 UINT32 DestinationSize;\r
53 UINT32 ScratchSize;\r
54 VOID *Scratch;\r
55 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
94020bb4 56 UINT32 InitializationSize;\r
9060e3ec 57\r
58 EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;\r
59 if ((EfiOpRomImageNode == NULL) ||\r
60 (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||\r
61 (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||\r
62 (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||\r
63 (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||\r
64 (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||\r
65 (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||\r
66 (BufferSize == NULL)\r
67 ) {\r
68 return EFI_INVALID_PARAMETER;\r
69 }\r
70\r
71 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (\r
72 (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset\r
73 );\r
74 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
75 return EFI_NOT_FOUND;\r
76 }\r
77\r
78\r
79 Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);\r
94020bb4 80 ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);\r
9060e3ec 81\r
82 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
83 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
84 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
85 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&\r
86 (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)\r
87 ) {\r
88\r
94020bb4 89 ImageSize = Pcir->ImageLength * 512;\r
90 InitializationSize = (UINT32) EfiRomHeader->InitializationSize * 512;\r
91 if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOffset >= InitializationSize) {\r
92 return EFI_NOT_FOUND;\r
93 }\r
94\r
9060e3ec 95 ImageBuffer = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;\r
94020bb4 96 ImageLength = InitializationSize - EfiRomHeader->EfiImageHeaderOffset;\r
9060e3ec 97\r
98 if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
99 //\r
100 // Uncompressed: Copy the EFI Image directly to user's buffer\r
101 //\r
102 if (Buffer == NULL || *BufferSize < ImageLength) {\r
103 *BufferSize = ImageLength;\r
104 return EFI_BUFFER_TOO_SMALL;\r
105 }\r
106\r
107 *BufferSize = ImageLength;\r
108 CopyMem (Buffer, ImageBuffer, ImageLength);\r
109 return EFI_SUCCESS;\r
110\r
111 } else {\r
112 //\r
113 // Compressed: Uncompress before copying\r
114 //\r
115 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
116 if (EFI_ERROR (Status)) {\r
117 return EFI_DEVICE_ERROR;\r
118 }\r
119 Status = Decompress->GetInfo (\r
120 Decompress,\r
121 ImageBuffer,\r
122 ImageLength,\r
123 &DestinationSize,\r
124 &ScratchSize\r
125 );\r
126 if (EFI_ERROR (Status)) {\r
127 return EFI_DEVICE_ERROR;\r
128 }\r
129\r
130 if (Buffer == NULL || *BufferSize < DestinationSize) {\r
131 *BufferSize = DestinationSize;\r
132 return EFI_BUFFER_TOO_SMALL;\r
133 }\r
134\r
135 *BufferSize = DestinationSize;\r
136 Scratch = AllocatePool (ScratchSize);\r
137 if (Scratch == NULL) {\r
138 return EFI_DEVICE_ERROR;\r
139 }\r
140\r
141 Status = Decompress->Decompress (\r
142 Decompress,\r
143 ImageBuffer,\r
144 ImageLength,\r
145 Buffer,\r
146 DestinationSize,\r
147 Scratch,\r
148 ScratchSize\r
149 );\r
150 FreePool (Scratch);\r
151\r
152 if (EFI_ERROR (Status)) {\r
153 return EFI_DEVICE_ERROR;\r
154 }\r
155 return EFI_SUCCESS;\r
156 }\r
157 }\r
158\r
159 return EFI_NOT_FOUND;\r
160}\r
161\r
162/**\r
163 Initialize a PCI LoadFile2 instance.\r
164\r
165 @param PciIoDevice PCI IO Device.\r
166\r
167**/\r
168VOID\r
169InitializePciLoadFile2 (\r
170 IN PCI_IO_DEVICE *PciIoDevice\r
171 )\r
172{\r
173 PciIoDevice->LoadFile2.LoadFile = LoadFile2;\r
174}\r
175\r
176/**\r
177 Causes the driver to load a specified file.\r
178\r
179 @param This Indicates a pointer to the calling context.\r
180 @param FilePath The device specific path of the file to load.\r
181 @param BootPolicy Should always be FALSE.\r
182 @param BufferSize On input the size of Buffer in bytes. On output with a return\r
183 code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
184 On output with a return code of EFI_BUFFER_TOO_SMALL,\r
185 the size of Buffer required to retrieve the requested file.\r
186 @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,\r
187 then no the size of the requested file is returned in BufferSize.\r
188\r
189 @retval EFI_SUCCESS The file was loaded.\r
190 @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
191 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
192 BufferSize is NULL.\r
193 @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.\r
194 @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.\r
195 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
196 BufferSize has been updated with the size needed to complete the request.\r
197\r
198**/\r
199EFI_STATUS\r
200EFIAPI\r
201LoadFile2 (\r
202 IN EFI_LOAD_FILE2_PROTOCOL *This,\r
203 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
204 IN BOOLEAN BootPolicy,\r
205 IN OUT UINTN *BufferSize,\r
206 IN VOID *Buffer OPTIONAL\r
207 )\r
208{\r
209 PCI_IO_DEVICE *PciIoDevice;\r
210\r
211 if (BootPolicy) {\r
212 return EFI_UNSUPPORTED;\r
213 }\r
214 PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);\r
215\r
216 return LocalLoadFile2 (\r
217 PciIoDevice,\r
218 FilePath,\r
219 BufferSize,\r
220 Buffer\r
221 );\r
222}\r
223\r
224/**\r
225 Get Pci device's oprom information.\r
226\r
227 @param PciIoDevice Input Pci device instance.\r
228 Output Pci device instance with updated OptionRom size.\r
229\r
230 @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
231 @retval EFI_SUCCESS Pci device has Option Rom.\r
232\r
233**/\r
234EFI_STATUS\r
235GetOpRomInfo (\r
236 IN OUT PCI_IO_DEVICE *PciIoDevice\r
237 )\r
238{\r
239 UINT8 RomBarIndex;\r
240 UINT32 AllOnes;\r
241 UINT64 Address;\r
242 EFI_STATUS Status;\r
243 UINT8 Bus;\r
244 UINT8 Device;\r
245 UINT8 Function;\r
246 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
247\r
248 Bus = PciIoDevice->BusNumber;\r
249 Device = PciIoDevice->DeviceNumber;\r
250 Function = PciIoDevice->FunctionNumber;\r
251\r
252 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
253\r
254 //\r
255 // Offset is 0x30 if is not ppb\r
256 //\r
257\r
258 //\r
259 // 0x30\r
260 //\r
261 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
262\r
263 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
264 //\r
265 // If is ppb, 0x38\r
266 //\r
267 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
268 }\r
269 //\r
270 // The bit0 is 0 to prevent the enabling of the Rom address decoder\r
271 //\r
272 AllOnes = 0xfffffffe;\r
273 Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
274\r
275 Status = PciRootBridgeIo->Pci.Write (\r
276 PciRootBridgeIo,\r
277 EfiPciWidthUint32,\r
278 Address,\r
279 1,\r
280 &AllOnes\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 return EFI_NOT_FOUND;\r
284 }\r
285\r
286 //\r
287 // Read back\r
288 //\r
289 Status = PciRootBridgeIo->Pci.Read(\r
290 PciRootBridgeIo,\r
291 EfiPciWidthUint32,\r
292 Address,\r
293 1,\r
294 &AllOnes\r
295 );\r
296 if (EFI_ERROR (Status)) {\r
297 return EFI_NOT_FOUND;\r
298 }\r
299\r
300 //\r
301 // Bits [1, 10] are reserved\r
302 //\r
303 AllOnes &= 0xFFFFF800;\r
304 if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
305 return EFI_NOT_FOUND;\r
306 }\r
307\r
308 PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
309 return EFI_SUCCESS;\r
310}\r
311\r
9060e3ec 312/**\r
313 Load Option Rom image for specified PCI device.\r
314\r
315 @param PciDevice Pci device instance.\r
316 @param RomBase Base address of Option Rom.\r
317\r
318 @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
319 @retval EFI_SUCESS Successfully loaded Option Rom.\r
320\r
321**/\r
322EFI_STATUS\r
323LoadOpRomImage (\r
324 IN PCI_IO_DEVICE *PciDevice,\r
325 IN UINT64 RomBase\r
326 )\r
327{\r
328 UINT8 RomBarIndex;\r
329 UINT8 Indicator;\r
330 UINT16 OffsetPcir;\r
331 UINT32 RomBarOffset;\r
332 UINT32 RomBar;\r
333 EFI_STATUS RetStatus;\r
334 BOOLEAN FirstCheck;\r
335 UINT8 *Image;\r
336 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
337 PCI_DATA_STRUCTURE *RomPcir;\r
338 UINT64 RomSize;\r
339 UINT64 RomImageSize;\r
94020bb4 340 UINT32 LegacyImageLength;\r
9060e3ec 341 UINT8 *RomInMemory;\r
342 UINT8 CodeType;\r
7d921075 343 BOOLEAN HasEfiOpRom;\r
9060e3ec 344\r
345 RomSize = PciDevice->RomSize;\r
346\r
347 Indicator = 0;\r
348 RomImageSize = 0;\r
349 RomInMemory = NULL;\r
350 CodeType = 0xFF;\r
351\r
352 //\r
353 // Get the RomBarIndex\r
354 //\r
355\r
356 //\r
357 // 0x30\r
358 //\r
359 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
360 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
361 //\r
362 // if is ppb\r
363 //\r
364\r
365 //\r
366 // 0x38\r
367 //\r
368 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
369 }\r
370 //\r
371 // Allocate memory for Rom header and PCIR\r
372 //\r
373 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
374 if (RomHeader == NULL) {\r
375 return EFI_OUT_OF_RESOURCES;\r
376 }\r
377\r
378 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
379 if (RomPcir == NULL) {\r
380 FreePool (RomHeader);\r
381 return EFI_OUT_OF_RESOURCES;\r
382 }\r
383\r
384 RomBar = (UINT32) RomBase;\r
385\r
386 //\r
387 // Enable RomBar\r
388 //\r
389 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
390\r
391 RomBarOffset = RomBar;\r
392 RetStatus = EFI_NOT_FOUND;\r
393 FirstCheck = TRUE;\r
94020bb4 394 LegacyImageLength = 0;\r
7d921075 395 HasEfiOpRom = FALSE;\r
9060e3ec 396\r
397 do {\r
398 PciDevice->PciRootBridgeIo->Mem.Read (\r
399 PciDevice->PciRootBridgeIo,\r
400 EfiPciWidthUint8,\r
401 RomBarOffset,\r
402 sizeof (PCI_EXPANSION_ROM_HEADER),\r
403 (UINT8 *) RomHeader\r
404 );\r
405\r
406 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
407 RomBarOffset = RomBarOffset + 512;\r
408 if (FirstCheck) {\r
409 break;\r
410 } else {\r
411 RomImageSize = RomImageSize + 512;\r
412 continue;\r
413 }\r
414 }\r
415\r
416 FirstCheck = FALSE;\r
417 OffsetPcir = RomHeader->PcirOffset;\r
94020bb4 418 //\r
419 // If the pointer to the PCI Data Structure is invalid, no further images can be located. \r
420 // The PCI Data Structure must be DWORD aligned. \r
421 //\r
422 if (OffsetPcir == 0 ||\r
423 (OffsetPcir & 3) != 0 ||\r
424 RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {\r
425 break;\r
426 }\r
9060e3ec 427 PciDevice->PciRootBridgeIo->Mem.Read (\r
428 PciDevice->PciRootBridgeIo,\r
429 EfiPciWidthUint8,\r
430 RomBarOffset + OffsetPcir,\r
431 sizeof (PCI_DATA_STRUCTURE),\r
432 (UINT8 *) RomPcir\r
433 );\r
94020bb4 434 //\r
435 // If a valid signature is not present in the PCI Data Structure, no further images can be located.\r
436 //\r
437 if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
438 break;\r
439 }\r
440 if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {\r
441 break;\r
442 }\r
9060e3ec 443 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
444 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
94020bb4 445 LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;\r
7d921075
RN
446 } else if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
447 HasEfiOpRom = TRUE;\r
9060e3ec 448 }\r
449 Indicator = RomPcir->Indicator;\r
450 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
451 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
452 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
453\r
454 //\r
455 // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
456 // of the legacy length and the PCIR Image Length\r
457 //\r
458 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
94020bb4 459 RomImageSize = MAX (RomImageSize, LegacyImageLength);\r
9060e3ec 460 }\r
461\r
462 if (RomImageSize > 0) {\r
463 RetStatus = EFI_SUCCESS;\r
464 Image = AllocatePool ((UINT32) RomImageSize);\r
465 if (Image == NULL) {\r
466 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
467 FreePool (RomHeader);\r
468 FreePool (RomPcir);\r
469 return EFI_OUT_OF_RESOURCES;\r
470 }\r
471\r
472 //\r
473 // Copy Rom image into memory\r
474 //\r
475 PciDevice->PciRootBridgeIo->Mem.Read (\r
476 PciDevice->PciRootBridgeIo,\r
477 EfiPciWidthUint8,\r
478 RomBar,\r
479 (UINT32) RomImageSize,\r
480 Image\r
481 );\r
482 RomInMemory = Image;\r
483 }\r
484\r
485 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
486\r
7d921075 487 PciDevice->HasEfiOpRom = HasEfiOpRom;\r
4ed4e19c 488 PciDevice->EmbeddedRom = TRUE;\r
9060e3ec 489 PciDevice->PciIo.RomSize = RomImageSize;\r
490 PciDevice->PciIo.RomImage = RomInMemory;\r
491\r
492 //\r
493 // For OpROM read from PCI device:\r
494 // Add the Rom Image to internal database for later PCI light enumeration\r
495 //\r
496 PciRomAddImageMapping (\r
497 NULL,\r
498 PciDevice->PciRootBridgeIo->SegmentNumber,\r
499 PciDevice->BusNumber,\r
500 PciDevice->DeviceNumber,\r
501 PciDevice->FunctionNumber,\r
502 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
503 PciDevice->PciIo.RomSize\r
504 );\r
505\r
506 //\r
507 // Free allocated memory\r
508 //\r
509 FreePool (RomHeader);\r
510 FreePool (RomPcir);\r
511\r
512 return RetStatus;\r
513}\r
514\r
515/**\r
516 Enable/Disable Option Rom decode.\r
517\r
518 @param PciDevice Pci device instance.\r
519 @param RomBarIndex The BAR index of the standard PCI Configuration header to use as the\r
520 base address for resource range. The legal range for this field is 0..5.\r
521 @param RomBar Base address of Option Rom.\r
522 @param Enable Flag for enable/disable decode.\r
523\r
524**/\r
525VOID\r
526RomDecode (\r
527 IN PCI_IO_DEVICE *PciDevice,\r
528 IN UINT8 RomBarIndex,\r
529 IN UINT32 RomBar,\r
530 IN BOOLEAN Enable\r
531 )\r
532{\r
533 UINT32 Value32;\r
534 UINT32 Offset;\r
6989af71 535 UINT32 OffsetMax;\r
9060e3ec 536 EFI_PCI_IO_PROTOCOL *PciIo;\r
537\r
538 PciIo = &PciDevice->PciIo;\r
539 if (Enable) {\r
540 //\r
541 // Clear all bars\r
542 //\r
6989af71
RN
543 OffsetMax = 0x24;\r
544 if (IS_PCI_BRIDGE(&PciDevice->Pci)) {\r
545 OffsetMax = 0x14;\r
546 }\r
547\r
548 for (Offset = 0x10; Offset <= OffsetMax; Offset += sizeof (UINT32)) {\r
9060e3ec 549 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
550 }\r
551\r
552 //\r
553 // set the Rom base address: now is hardcode\r
554 // enable its decoder\r
555 //\r
556 Value32 = RomBar | 0x1;\r
557 PciIo->Pci.Write (\r
558 PciIo,\r
559 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
560 RomBarIndex,\r
561 1,\r
562 &Value32\r
563 );\r
564\r
565 //\r
566 // Programe all upstream bridge\r
567 //\r
568 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
569\r
570 //\r
571 // Setting the memory space bit in the function's command register\r
572 //\r
573 PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
574\r
575 } else {\r
576\r
577 //\r
578 // disable command register decode to memory\r
579 //\r
580 PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
581\r
582 //\r
583 // Destroy the programmed bar in all the upstream bridge.\r
584 //\r
585 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
586\r
587 //\r
588 // disable rom decode\r
589 //\r
590 Value32 = 0xFFFFFFFE;\r
591 PciIo->Pci.Write (\r
592 PciIo,\r
593 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
594 RomBarIndex,\r
595 1,\r
596 &Value32\r
597 );\r
598\r
599 }\r
600}\r
601\r
602/**\r
603 Load and start the Option Rom image.\r
604\r
605 @param PciDevice Pci device instance.\r
606\r
607 @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom image.\r
608 @retval EFI_NOT_FOUND Failed to process PCI Option Rom image.\r
609\r
610**/\r
611EFI_STATUS\r
612ProcessOpRomImage (\r
613 IN PCI_IO_DEVICE *PciDevice\r
614 )\r
615{\r
616 UINT8 Indicator;\r
617 UINT32 ImageSize;\r
618 VOID *RomBar;\r
619 UINT8 *RomBarOffset;\r
620 EFI_HANDLE ImageHandle;\r
621 EFI_STATUS Status;\r
622 EFI_STATUS RetStatus;\r
9060e3ec 623 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
624 PCI_DATA_STRUCTURE *Pcir;\r
625 EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;\r
626 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode;\r
627 VOID *Buffer;\r
628 UINTN BufferSize;\r
629\r
630 Indicator = 0;\r
631\r
632 //\r
633 // Get the Address of the Option Rom image\r
634 //\r
635 RomBar = PciDevice->PciIo.RomImage;\r
636 RomBarOffset = (UINT8 *) RomBar;\r
637 RetStatus = EFI_NOT_FOUND;\r
94020bb4 638\r
639 if (RomBar == NULL) {\r
640 return RetStatus;\r
641 }\r
642 ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);\r
9060e3ec 643\r
644 do {\r
645 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
646 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
647 RomBarOffset += 512;\r
94020bb4 648 continue;\r
9060e3ec 649 }\r
650\r
9060e3ec 651 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
94020bb4 652 ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);\r
9060e3ec 653 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
654 Indicator = Pcir->Indicator;\r
655\r
a93e23f9 656 //\r
657 // Skip the image if it is not an EFI PCI Option ROM image\r
658 //\r
659 if (Pcir->CodeType != PCI_CODE_TYPE_EFI_IMAGE) {\r
660 goto NextImage;\r
661 }\r
662\r
663 //\r
664 // Skip the EFI PCI Option ROM image if its machine type is not supported\r
665 //\r
666 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (EfiRomHeader->EfiMachineType)) {\r
667 goto NextImage;\r
668 }\r
669\r
670 //\r
671 // Ignore the EFI PCI Option ROM image if it is an EFI application\r
672 //\r
673 if (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
674 goto NextImage;\r
675 }\r
676\r
9060e3ec 677 //\r
678 // Create Pci Option Rom Image device path header\r
679 //\r
680 EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;\r
681 EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
682 SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
683 EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;\r
684 EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
685\r
686 PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
687 ASSERT (PciOptionRomImageDevicePath != NULL);\r
688\r
689 //\r
690 // load image and start image\r
691 //\r
692 BufferSize = 0;\r
693 Buffer = NULL;\r
9060e3ec 694 ImageHandle = NULL;\r
695\r
a93e23f9 696 Status = gBS->LoadImage (\r
697 FALSE,\r
698 gPciBusDriverBinding.DriverBindingHandle,\r
699 PciOptionRomImageDevicePath,\r
700 Buffer,\r
701 BufferSize,\r
702 &ImageHandle\r
703 );\r
9060e3ec 704\r
705 FreePool (PciOptionRomImageDevicePath);\r
706\r
707 if (!EFI_ERROR (Status)) {\r
708 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
709 if (!EFI_ERROR (Status)) {\r
710 AddDriver (PciDevice, ImageHandle);\r
711 PciRomAddImageMapping (\r
712 ImageHandle,\r
713 PciDevice->PciRootBridgeIo->SegmentNumber,\r
714 PciDevice->BusNumber,\r
715 PciDevice->DeviceNumber,\r
716 PciDevice->FunctionNumber,\r
717 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
718 PciDevice->PciIo.RomSize\r
719 );\r
720 RetStatus = EFI_SUCCESS;\r
721 }\r
722 }\r
723\r
a93e23f9 724NextImage:\r
9060e3ec 725 RomBarOffset += ImageSize;\r
726\r
727 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
728\r
729 return RetStatus;\r
730}\r
731\r