]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
Loaded Image device paths for EFI Drivers loaded from PCI Option ROM
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciOptionRomSupport.c
CommitLineData
eeefcb9d 1/** @file\r
3db51098 2\r
05975035 3Copyright (c) 2006 - 2008, Intel Corporation\r
cfe9de52 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
3db51098 11\r
12**/\r
ead42efc 13\r
03417d8d 14#include "PciBus.h"\r
ead42efc 15#include "PciResourceSupport.h"\r
16\r
b1ef4015 17#include <IndustryStandard/Pci23.h>\r
ead42efc 18\r
8e6b0dcb 19/**\r
20 Load the EFI Image from Option ROM\r
21 \r
22 @param PciIoDevice PCI IO Device\r
23 @param FilePath The file path of the EFI Image\r
24 @param BufferSize On input the size of Buffer in bytes. On output with a return \r
25 code of EFI_SUCCESS, the amount of data transferred to Buffer. \r
26 On output with a return code of EFI_BUFFER_TOO_SMALL, \r
27 the size of Buffer required to retrieve the requested file. \r
28 @param Buffer The memory buffer to transfer the file to. If Buffer is NULL, \r
29 then no the size of the requested file is returned in BufferSize.\r
30\r
31 @retval EFI_SUCCESS The file was loaded. \r
32 @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
33 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
34 BufferSize has been updated with the size needed to complete the request.\r
35**/\r
36EFI_STATUS\r
37LocalLoadFile2 (\r
38 IN PCI_IO_DEVICE *PciIoDevice,\r
39 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
40 IN OUT UINTN *BufferSize,\r
41 IN VOID *Buffer OPTIONAL\r
42 )\r
43{\r
44 EFI_STATUS Status;\r
45 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *EfiOpRomImageNode;\r
46 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
47 PCI_DATA_STRUCTURE *Pcir;\r
48 UINT32 ImageSize;\r
49 UINT8 *ImageBuffer;\r
50 UINT32 ImageLength;\r
51 UINT32 DestinationSize;\r
52 UINT32 ScratchSize;\r
53 VOID *Scratch;\r
54 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
55\r
56 EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;\r
57 if ((EfiOpRomImageNode == NULL) ||\r
58 (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||\r
59 (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||\r
60 (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||\r
61 (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||\r
62 (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||\r
63 (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||\r
64 (BufferSize == NULL)\r
65 ) {\r
66 return EFI_INVALID_PARAMETER;\r
67 }\r
68 \r
69 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (\r
70 (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset\r
71 );\r
72 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
73 return EFI_NOT_FOUND;\r
74 }\r
75\r
76 \r
77 Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);\r
78\r
79 \r
80 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && \r
81 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
82 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
83 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&\r
84 (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)\r
85 ) {\r
86\r
87 ImageSize = (UINT32) EfiRomHeader->InitializationSize * 512;\r
88 \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, &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 gBS->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 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_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
186 BufferSize has been updated with the size needed to complete the request.\r
187 \r
188**/\r
189EFI_STATUS\r
190EFIAPI\r
191LoadFile2 (\r
192 IN EFI_LOAD_FILE2_PROTOCOL *This,\r
193 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
194 IN BOOLEAN BootPolicy,\r
195 IN OUT UINTN *BufferSize,\r
196 IN VOID *Buffer OPTIONAL\r
197 )\r
198{\r
199 PCI_IO_DEVICE *PciIoDevice;\r
200\r
201 if (BootPolicy) {\r
202 return EFI_UNSUPPORTED;\r
203 }\r
204 PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);\r
205\r
206 return LocalLoadFile2 (\r
207 PciIoDevice,\r
208 FilePath,\r
209 BufferSize,\r
210 Buffer\r
211 );\r
212}\r
213\r
214\r
2d9d2abf 215//\r
216// Module global for a template of the PCI option ROM Image Device Path Node\r
217//\r
218MEMMAP_DEVICE_PATH mPciOptionRomImageDevicePathNodeTemplate = {\r
cfe9de52 219 {\r
2d9d2abf 220 HARDWARE_DEVICE_PATH,\r
221 HW_MEMMAP_DP,\r
05975035 222 {\r
223 (UINT8) (sizeof (MEMMAP_DEVICE_PATH)),\r
224 (UINT8) ((sizeof (MEMMAP_DEVICE_PATH)) >> 8)\r
225 }\r
2d9d2abf 226 },\r
227 EfiMemoryMappedIO,\r
228 0,\r
229 0\r
230};\r
231\r
57076f45 232/**\r
233 Get Pci device's oprom infor bits.\r
234 \r
eeefcb9d 235 @param PciIoDevice Pci device instance\r
236\r
57076f45 237 @retval EFI_NOT_FOUND Pci device has not oprom\r
238 @retval EFI_SUCCESS Pci device has oprom\r
239**/\r
ead42efc 240EFI_STATUS\r
241GetOpRomInfo (\r
242 IN PCI_IO_DEVICE *PciIoDevice\r
243 )\r
ead42efc 244{\r
245 UINT8 RomBarIndex;\r
246 UINT32 AllOnes;\r
247 UINT64 Address;\r
248 EFI_STATUS Status;\r
249 UINT8 Bus;\r
250 UINT8 Device;\r
251 UINT8 Function;\r
252 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
253\r
254 Bus = PciIoDevice->BusNumber;\r
255 Device = PciIoDevice->DeviceNumber;\r
256 Function = PciIoDevice->FunctionNumber;\r
257\r
258 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
259\r
260 //\r
261 // offset is 0x30 if is not ppb\r
262 //\r
263\r
264 //\r
265 // 0x30\r
266 //\r
bc14bdb3 267 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
ead42efc 268\r
269 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
270 //\r
271 // if is ppb\r
272 //\r
273\r
274 //\r
275 // 0x38\r
276 //\r
277 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
278 }\r
279 //\r
280 // the bit0 is 0 to prevent the enabling of the Rom address decoder\r
281 //\r
282 AllOnes = 0xfffffffe;\r
283 Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
284\r
285 Status = PciRootBridgeIoWrite (\r
286 PciRootBridgeIo,\r
287 &PciIoDevice->Pci,\r
288 EfiPciWidthUint32,\r
289 Address,\r
290 1,\r
291 &AllOnes\r
292 );\r
293 if (EFI_ERROR (Status)) {\r
294 return Status;\r
295 }\r
296\r
297 //\r
298 // read back\r
299 //\r
300 Status = PciRootBridgeIoRead (\r
301 PciRootBridgeIo,\r
302 &PciIoDevice->Pci,\r
303 EfiPciWidthUint32,\r
304 Address,\r
305 1,\r
306 &AllOnes\r
307 );\r
308 if (EFI_ERROR (Status)) {\r
309 return Status;\r
310 }\r
311 //\r
312 // Bits [1, 10] are reserved\r
313 //\r
314 AllOnes &= 0xFFFFF800;\r
315 if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
316 return EFI_NOT_FOUND;\r
317 }\r
318\r
319 PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
320 return EFI_SUCCESS;\r
321}\r
322\r
8e6b0dcb 323/**\r
324\r
325 Check if the RomImage contains EFI Images.\r
326\r
327 @param RomImage The ROM address of Image for check. \r
328 @param RomSize Size of ROM for check.\r
329\r
330 @retval TRUE ROM contain EFI Image.\r
331 @retval FALSE ROM not contain EFI Image.\r
332 \r
333**/\r
334BOOLEAN\r
335ContainEfiImage (\r
336 IN VOID *RomImage,\r
337 IN UINT64 RomSize\r
338 ) \r
339{\r
340 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
341 PCI_DATA_STRUCTURE *RomPcir;\r
342 BOOLEAN FirstCheck;\r
343\r
344 FirstCheck = TRUE;\r
345 RomHeader = RomImage;\r
346 \r
347 while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) {\r
348 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
349 if (FirstCheck) {\r
350 return FALSE;\r
351 } else {\r
352 RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);\r
353 continue;\r
354 }\r
355 }\r
356\r
357 FirstCheck = FALSE;\r
358 RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);\r
359 \r
360 if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
361 return TRUE;\r
362 }\r
363\r
364 RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512);\r
365 }\r
366\r
367 return FALSE;\r
368}\r
369\r
370\r
57076f45 371/**\r
372 Load option rom image for specified PCI device\r
373 \r
374 @param PciDevice Pci device instance\r
375 @param RomBase Base address of oprom.\r
376 \r
377 @retval EFI_OUT_OF_RESOURCES not enough memory to hold image\r
378 @retval EFI_SUCESS Success\r
379**/\r
ead42efc 380EFI_STATUS\r
381LoadOpRomImage (\r
382 IN PCI_IO_DEVICE *PciDevice,\r
383 IN UINT64 RomBase\r
384 )\r
ead42efc 385{\r
386 UINT8 RomBarIndex;\r
387 UINT8 Indicator;\r
388 UINT16 OffsetPcir;\r
389 UINT32 RomBarOffset;\r
390 UINT32 RomBar;\r
5326528b 391 EFI_STATUS RetStatus;\r
ead42efc 392 BOOLEAN FirstCheck;\r
393 UINT8 *Image;\r
394 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
395 PCI_DATA_STRUCTURE *RomPcir;\r
396 UINT64 RomSize;\r
397 UINT64 RomImageSize;\r
398 UINT8 *RomInMemory;\r
399 UINT8 CodeType;\r
400\r
401 RomSize = PciDevice->RomSize;\r
402\r
403 Indicator = 0;\r
404 RomImageSize = 0;\r
405 RomInMemory = NULL;\r
406 CodeType = 0xFF;\r
407\r
408 //\r
409 // Get the RomBarIndex\r
410 //\r
411\r
412 //\r
413 // 0x30\r
414 //\r
bc14bdb3 415 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
ead42efc 416 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
417 //\r
418 // if is ppb\r
419 //\r
420\r
421 //\r
422 // 0x38\r
423 //\r
424 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
425 }\r
426 //\r
427 // Allocate memory for Rom header and PCIR\r
428 //\r
429 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
430 if (RomHeader == NULL) {\r
431 return EFI_OUT_OF_RESOURCES;\r
432 }\r
433\r
434 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
435 if (RomPcir == NULL) {\r
436 gBS->FreePool (RomHeader);\r
437 return EFI_OUT_OF_RESOURCES;\r
438 }\r
439\r
440 RomBar = (UINT32) RomBase;\r
441\r
442 //\r
443 // Enable RomBar\r
444 //\r
445 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
446\r
447 RomBarOffset = RomBar;\r
5326528b 448 RetStatus = EFI_NOT_FOUND;\r
ead42efc 449 FirstCheck = TRUE;\r
450\r
451 do {\r
452 PciDevice->PciRootBridgeIo->Mem.Read (\r
453 PciDevice->PciRootBridgeIo,\r
454 EfiPciWidthUint8,\r
455 RomBarOffset,\r
456 sizeof (PCI_EXPANSION_ROM_HEADER),\r
457 (UINT8 *) RomHeader\r
458 );\r
459\r
460 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
461 RomBarOffset = RomBarOffset + 512;\r
462 if (FirstCheck) {\r
463 break;\r
464 } else {\r
465 RomImageSize = RomImageSize + 512;\r
466 continue;\r
467 }\r
468 }\r
469\r
470 FirstCheck = FALSE;\r
471 OffsetPcir = RomHeader->PcirOffset;\r
472 PciDevice->PciRootBridgeIo->Mem.Read (\r
473 PciDevice->PciRootBridgeIo,\r
474 EfiPciWidthUint8,\r
475 RomBarOffset + OffsetPcir,\r
476 sizeof (PCI_DATA_STRUCTURE),\r
477 (UINT8 *) RomPcir\r
478 );\r
479 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
480 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
481 }\r
482 Indicator = RomPcir->Indicator;\r
483 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
484 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
485 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
486\r
487 //\r
488 // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
489 // of the legacy length and the PCIR Image Length\r
490 //\r
491 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
a1e3528b 492 RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
ead42efc 493 }\r
494\r
495 if (RomImageSize > 0) {\r
5326528b 496 RetStatus = EFI_SUCCESS;\r
ead42efc 497 Image = AllocatePool ((UINT32) RomImageSize);\r
498 if (Image == NULL) {\r
499 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
500 gBS->FreePool (RomHeader);\r
501 gBS->FreePool (RomPcir);\r
502 return EFI_OUT_OF_RESOURCES;\r
503 }\r
cfe9de52 504\r
ead42efc 505 //\r
506 // Copy Rom image into memory\r
507 //\r
508 PciDevice->PciRootBridgeIo->Mem.Read (\r
509 PciDevice->PciRootBridgeIo,\r
510 EfiPciWidthUint8,\r
511 RomBar,\r
512 (UINT32) RomImageSize,\r
513 Image\r
514 );\r
515 RomInMemory = Image;\r
516 }\r
517\r
518 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
519\r
520 PciDevice->PciIo.RomSize = RomImageSize;\r
521 PciDevice->PciIo.RomImage = RomInMemory;\r
522\r
96d1b172 523 //\r
524 // For OpROM read from PCI device:\r
525 // Add the Rom Image to internal database for later PCI light enumeration\r
526 //\r
ead42efc 527 PciRomAddImageMapping (\r
528 NULL,\r
529 PciDevice->PciRootBridgeIo->SegmentNumber,\r
530 PciDevice->BusNumber,\r
531 PciDevice->DeviceNumber,\r
532 PciDevice->FunctionNumber,\r
533 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
534 PciDevice->PciIo.RomSize\r
535 );\r
536\r
537 //\r
538 // Free allocated memory\r
539 //\r
540 gBS->FreePool (RomHeader);\r
541 gBS->FreePool (RomPcir);\r
542\r
5326528b 543 return RetStatus;\r
ead42efc 544}\r
545\r
57076f45 546/**\r
547 enable/disable oprom decode\r
548 \r
549 @param PciDevice pci device instance\r
550 @param RomBarIndex The BAR index of the standard PCI Configuration header to use as the\r
551 base address for resource range. The legal range for this field is 0..5.\r
552 @param RomBar Base address of rom\r
553 @param Enable Flag for enable/disable decode.\r
554 \r
555 @retval EFI_SUCCESS Success\r
556**/\r
ead42efc 557EFI_STATUS\r
558RomDecode (\r
559 IN PCI_IO_DEVICE *PciDevice,\r
560 IN UINT8 RomBarIndex,\r
561 IN UINT32 RomBar,\r
562 IN BOOLEAN Enable\r
563 )\r
ead42efc 564{\r
565 UINT32 Value32;\r
566 UINT32 Offset;\r
567 EFI_PCI_IO_PROTOCOL *PciIo;\r
568\r
569 PciIo = &PciDevice->PciIo;\r
570 if (Enable) {\r
571 //\r
572 // Clear all bars\r
573 //\r
574 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
575 PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
576 }\r
cfe9de52 577\r
ead42efc 578 //\r
579 // set the Rom base address: now is hardcode\r
580 // enable its decoder\r
581 //\r
582 Value32 = RomBar | 0x1;\r
583 PciIoWrite (\r
584 PciIo,\r
585 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
586 RomBarIndex,\r
587 1,\r
588 &Value32\r
589 );\r
590\r
591 //\r
592 // Programe all upstream bridge\r
593 //\r
594 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
595\r
596 //\r
597 // Setting the memory space bit in the function's command register\r
598 //\r
599 PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
600\r
601 } else {\r
cfe9de52 602\r
ead42efc 603 //\r
604 // disable command register decode to memory\r
605 //\r
606 PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
607\r
608 //\r
609 // Destroy the programmed bar in all the upstream bridge.\r
610 //\r
611 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
612\r
613 //\r
614 // disable rom decode\r
615 //\r
616 Value32 = 0xFFFFFFFE;\r
617 PciIoWrite (\r
618 PciIo,\r
619 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
620 RomBarIndex,\r
621 1,\r
622 &Value32\r
623 );\r
624\r
625 }\r
626\r
627 return EFI_SUCCESS;\r
628\r
629}\r
630\r
57076f45 631/**\r
632 Process the oprom image.\r
633 \r
634 @param PciDevice Pci device instance\r
635**/\r
ead42efc 636EFI_STATUS\r
637ProcessOpRomImage (\r
638 PCI_IO_DEVICE *PciDevice\r
639 )\r
ead42efc 640{\r
641 UINT8 Indicator;\r
642 UINT32 ImageSize;\r
ead42efc 643 VOID *RomBar;\r
644 UINT8 *RomBarOffset;\r
645 EFI_HANDLE ImageHandle;\r
646 EFI_STATUS Status;\r
5326528b 647 EFI_STATUS RetStatus;\r
ead42efc 648 BOOLEAN FirstCheck;\r
ead42efc 649 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
650 PCI_DATA_STRUCTURE *Pcir;\r
2d9d2abf 651 EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;\r
ead42efc 652\r
8e6b0dcb 653 MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode; \r
654 VOID *Buffer;\r
655 UINTN BufferSize;\r
656\r
ead42efc 657 Indicator = 0;\r
658\r
659 //\r
660 // Get the Address of the Rom image\r
661 //\r
662 RomBar = PciDevice->PciIo.RomImage;\r
663 RomBarOffset = (UINT8 *) RomBar;\r
5326528b 664 RetStatus = EFI_NOT_FOUND;\r
ead42efc 665 FirstCheck = TRUE;\r
666\r
667 do {\r
668 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
669 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
8e6b0dcb 670 RomBarOffset += 512;\r
ead42efc 671 if (FirstCheck) {\r
672 break;\r
673 } else {\r
674 continue;\r
675 }\r
676 }\r
677\r
678 FirstCheck = FALSE;\r
679 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
680 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
681 Indicator = Pcir->Indicator;\r
682\r
8e6b0dcb 683 //\r
684 // Create Pci Option Rom Image device path header\r
685 //\r
686 EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;\r
687 EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
688 SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
689 EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;\r
690 EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
ead42efc 691\r
8e6b0dcb 692 PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
693 ASSERT (PciOptionRomImageDevicePath != NULL);\r
694\r
695 //\r
696 // load image and start image\r
697 //\r
698\r
699 BufferSize = 0;\r
700 Buffer = NULL;\r
701 Status = EFI_SUCCESS;\r
702 ImageHandle = NULL;\r
703\r
704 if (!EFI_ERROR (Status)) {\r
705 Status = gBS->LoadImage (\r
706 FALSE,\r
707 gPciBusDriverBinding.DriverBindingHandle,\r
708 PciOptionRomImageDevicePath,\r
709 Buffer,\r
710 BufferSize,\r
711 &ImageHandle\r
712 );\r
713 }\r
714\r
715 //\r
716 // load image and start image\r
717 //\r
718 if (!EFI_ERROR (Status)) {\r
719 Status = gBS->LoadImage (\r
720 FALSE,\r
721 gPciBusDriverBinding.DriverBindingHandle,\r
722 PciOptionRomImageDevicePath,\r
723 Buffer,\r
724 BufferSize,\r
725 &ImageHandle\r
726 );\r
727 }\r
728\r
729 gBS->FreePool (PciOptionRomImageDevicePath);\r
730\r
731 if (!EFI_ERROR (Status)) {\r
732 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
733 if (!EFI_ERROR (Status)) {\r
734 AddDriver (PciDevice, ImageHandle);\r
735 PciRomAddImageMapping (\r
736 ImageHandle,\r
737 PciDevice->PciRootBridgeIo->SegmentNumber,\r
738 PciDevice->BusNumber,\r
739 PciDevice->DeviceNumber,\r
740 PciDevice->FunctionNumber,\r
741 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
742 PciDevice->PciIo.RomSize\r
743 );\r
744 RetStatus = EFI_SUCCESS;\r
ead42efc 745 }\r
ead42efc 746 }\r
747\r
8e6b0dcb 748 RomBarOffset += ImageSize;\r
749\r
ead42efc 750 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
751\r
5326528b 752 return RetStatus;\r
ead42efc 753\r
754}\r
57076f45 755\r