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