summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/Library
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/Library')
-rw-r--r--OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c184
-rw-r--r--OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h3
-rw-r--r--OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf3
3 files changed, 189 insertions, 1 deletions
diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index 7c54fc5791..27ef7b90a5 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -32,6 +32,17 @@ InstallDevicePathCallback (
VOID
);
+STATIC
+VOID
+LoadVideoRom (
+ );
+
+STATIC
+EFI_STATUS
+PciRomLoadEfiDriversFromRomImage (
+ IN EFI_PHYSICAL_ADDRESS Rom,
+ IN UINTN RomSize
+ );
//
// BDS Platform Functions
@@ -58,6 +69,7 @@ Returns:
{
DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));
InstallDevicePathCallback ();
+ LoadVideoRom ();
}
@@ -1203,3 +1215,175 @@ LockKeyboards (
{
return EFI_UNSUPPORTED;
}
+
+
+STATIC
+VOID
+LoadVideoRom (
+ )
+{
+ PCI_DATA_STRUCTURE *Pcir;
+ UINTN RomSize;
+
+ //
+ // The virtual machines sometimes load the video rom image
+ // directly at the legacy video BIOS location of C000:0000,
+ // and do not implement the PCI expansion ROM feature.
+ //
+ Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;
+ RomSize = Pcir->ImageLength * 512;
+ PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);
+}
+
+
+STATIC
+EFI_STATUS
+PciRomLoadEfiDriversFromRomImage (
+ IN EFI_PHYSICAL_ADDRESS Rom,
+ IN UINTN RomSize
+ )
+{
+ CHAR16 *FileName;
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
+ PCI_DATA_STRUCTURE *Pcir;
+ UINTN ImageIndex;
+ UINTN RomOffset;
+ UINT32 ImageSize;
+ UINT16 ImageOffset;
+ EFI_HANDLE ImageHandle;
+ EFI_STATUS Status;
+ EFI_STATUS retStatus;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ BOOLEAN SkipImage;
+ UINT32 DestinationSize;
+ UINT32 ScratchSize;
+ UINT8 *Scratch;
+ VOID *ImageBuffer;
+ VOID *DecompressedImageBuffer;
+ UINT32 ImageLength;
+ EFI_DECOMPRESS_PROTOCOL *Decompress;
+
+ FileName = L"PciRomInMemory";
+
+ //FileName = L"PciRom Addr=0000000000000000";
+ //HexToString (&FileName[12], Rom, 16);
+
+ ImageIndex = 0;
+ retStatus = EFI_NOT_FOUND;
+ RomOffset = (UINTN) Rom;
+
+ do {
+
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;
+
+ if (EfiRomHeader->Signature != 0xaa55) {
+ return retStatus;
+ }
+
+ Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);
+ ImageSize = Pcir->ImageLength * 512;
+
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
+
+ if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
+
+ ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
+ ImageSize = EfiRomHeader->InitializationSize * 512;
+
+ ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);
+ ImageLength = ImageSize - ImageOffset;
+ DecompressedImageBuffer = NULL;
+
+ //
+ // decompress here if needed
+ //
+ SkipImage = FALSE;
+ if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ SkipImage = TRUE;
+ }
+
+ if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+ if (EFI_ERROR (Status)) {
+ SkipImage = TRUE;
+ } else {
+ SkipImage = TRUE;
+ Status = Decompress->GetInfo (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ &DestinationSize,
+ &ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ DecompressedImageBuffer = NULL;
+ DecompressedImageBuffer = AllocatePool (DestinationSize);
+ if (DecompressedImageBuffer != NULL) {
+ Scratch = AllocatePool (ScratchSize);
+ if (Scratch != NULL) {
+ Status = Decompress->Decompress (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ DecompressedImageBuffer,
+ DestinationSize,
+ Scratch,
+ ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ ImageBuffer = DecompressedImageBuffer;
+ ImageLength = DestinationSize;
+ SkipImage = FALSE;
+ }
+
+ gBS->FreePool (Scratch);
+ }
+ }
+ }
+ }
+ }
+
+ if (!SkipImage) {
+
+ //
+ // load image and start image
+ //
+
+ FilePath = FileDevicePath (NULL, FileName);
+
+ Status = gBS->LoadImage (
+ FALSE,
+ gImageHandle,
+ FilePath,
+ ImageBuffer,
+ ImageLength,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (!EFI_ERROR (Status)) {
+ retStatus = Status;
+ }
+ }
+ if (FilePath != NULL) {
+ gBS->FreePool (FilePath);
+ }
+ }
+
+ if (DecompressedImageBuffer != NULL) {
+ gBS->FreePool (DecompressedImageBuffer);
+ }
+
+ }
+ }
+
+ RomOffset = RomOffset + ImageSize;
+ ImageIndex++;
+ } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));
+
+ return retStatus;
+}
+
+
diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
index dc28515878..ef433c2370 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
@@ -29,7 +29,7 @@ Abstract:
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/SmBios.h>
-//#include <IndustryStandard/LegacyBiosMpTable.h>
+#include <IndustryStandard/PeImage.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
@@ -47,6 +47,7 @@ Abstract:
#include <Library/DevicePathLib.h>
#include <Library/IoLib.h>
+#include <Protocol/Decompress.h>
#include <Protocol/PciIo.h>
#include <Protocol/FirmwareVolume2.h>
diff --git a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index 1534ac8fc6..4689a79183 100644
--- a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -55,3 +55,6 @@
[Pcd.IA32, Pcd.X64]
gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+[Protocols]
+ gEfiDecompressProtocolGuid
+