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