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