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