]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
clear the correct BAR register. Because for P2P device, only register from 0x10 to...
[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
6989af71 4Copyright (c) 2006 - 2010, 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
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
6989af71 549 UINT32 OffsetMax;\r
9060e3ec 550 EFI_PCI_IO_PROTOCOL *PciIo;\r
551\r
552 PciIo = &PciDevice->PciIo;\r
553 if (Enable) {\r
554 //\r
555 // Clear all bars\r
556 //\r
6989af71
RN
557 OffsetMax = 0x24;\r
558 if (IS_PCI_BRIDGE(&PciDevice->Pci)) {\r
559 OffsetMax = 0x14;\r
560 }\r
561\r
562 for (Offset = 0x10; Offset <= OffsetMax; Offset += sizeof (UINT32)) {\r
9060e3ec 563 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
564 }\r
565\r
566 //\r
567 // set the Rom base address: now is hardcode\r
568 // enable its decoder\r
569 //\r
570 Value32 = RomBar | 0x1;\r
571 PciIo->Pci.Write (\r
572 PciIo,\r
573 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
574 RomBarIndex,\r
575 1,\r
576 &Value32\r
577 );\r
578\r
579 //\r
580 // Programe all upstream bridge\r
581 //\r
582 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
583\r
584 //\r
585 // Setting the memory space bit in the function's command register\r
586 //\r
587 PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
588\r
589 } else {\r
590\r
591 //\r
592 // disable command register decode to memory\r
593 //\r
594 PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
595\r
596 //\r
597 // Destroy the programmed bar in all the upstream bridge.\r
598 //\r
599 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
600\r
601 //\r
602 // disable rom decode\r
603 //\r
604 Value32 = 0xFFFFFFFE;\r
605 PciIo->Pci.Write (\r
606 PciIo,\r
607 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
608 RomBarIndex,\r
609 1,\r
610 &Value32\r
611 );\r
612\r
613 }\r
614}\r
615\r
616/**\r
617 Load and start the Option Rom image.\r
618\r
619 @param PciDevice Pci device instance.\r
620\r
621 @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom image.\r
622 @retval EFI_NOT_FOUND Failed to process PCI Option Rom image.\r
623\r
624**/\r
625EFI_STATUS\r
626ProcessOpRomImage (\r
627 IN PCI_IO_DEVICE *PciDevice\r
628 )\r
629{\r
630 UINT8 Indicator;\r
631 UINT32 ImageSize;\r
632 VOID *RomBar;\r
633 UINT8 *RomBarOffset;\r
634 EFI_HANDLE ImageHandle;\r
635 EFI_STATUS Status;\r
636 EFI_STATUS RetStatus;\r
637 BOOLEAN FirstCheck;\r
638 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
639 PCI_DATA_STRUCTURE *Pcir;\r
640 EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;\r
641 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode;\r
642 VOID *Buffer;\r
643 UINTN BufferSize;\r
644\r
645 Indicator = 0;\r
646\r
647 //\r
648 // Get the Address of the Option Rom image\r
649 //\r
650 RomBar = PciDevice->PciIo.RomImage;\r
651 RomBarOffset = (UINT8 *) RomBar;\r
652 RetStatus = EFI_NOT_FOUND;\r
653 FirstCheck = TRUE;\r
654\r
655 do {\r
656 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
657 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
658 RomBarOffset += 512;\r
659 if (FirstCheck) {\r
660 break;\r
661 } else {\r
662 continue;\r
663 }\r
664 }\r
665\r
666 FirstCheck = FALSE;\r
667 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
668 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
669 Indicator = Pcir->Indicator;\r
670\r
671 //\r
672 // Create Pci Option Rom Image device path header\r
673 //\r
674 EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;\r
675 EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
676 SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
677 EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;\r
678 EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
679\r
680 PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
681 ASSERT (PciOptionRomImageDevicePath != NULL);\r
682\r
683 //\r
684 // load image and start image\r
685 //\r
686 BufferSize = 0;\r
687 Buffer = NULL;\r
688 Status = EFI_SUCCESS;\r
689 ImageHandle = NULL;\r
690\r
691 if (!EFI_ERROR (Status)) {\r
692 Status = gBS->LoadImage (\r
693 FALSE,\r
694 gPciBusDriverBinding.DriverBindingHandle,\r
695 PciOptionRomImageDevicePath,\r
696 Buffer,\r
697 BufferSize,\r
698 &ImageHandle\r
699 );\r
700 }\r
701\r
702 //\r
703 // load image and start image\r
704 //\r
705 if (!EFI_ERROR (Status)) {\r
706 Status = gBS->LoadImage (\r
707 FALSE,\r
708 gPciBusDriverBinding.DriverBindingHandle,\r
709 PciOptionRomImageDevicePath,\r
710 Buffer,\r
711 BufferSize,\r
712 &ImageHandle\r
713 );\r
714 }\r
715\r
716 FreePool (PciOptionRomImageDevicePath);\r
717\r
718 if (!EFI_ERROR (Status)) {\r
719 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
720 if (!EFI_ERROR (Status)) {\r
721 AddDriver (PciDevice, ImageHandle);\r
722 PciRomAddImageMapping (\r
723 ImageHandle,\r
724 PciDevice->PciRootBridgeIo->SegmentNumber,\r
725 PciDevice->BusNumber,\r
726 PciDevice->DeviceNumber,\r
727 PciDevice->FunctionNumber,\r
728 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
729 PciDevice->PciIo.RomSize\r
730 );\r
731 RetStatus = EFI_SUCCESS;\r
732 }\r
733 }\r
734\r
735 RomBarOffset += ImageSize;\r
736\r
737 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
738\r
739 return RetStatus;\r
740}\r
741\r