summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/Csm
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-11-10 22:04:19 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2011-11-10 22:04:19 +0000
commit8016da21b56d5ab1da855037cd0f0e034e2404bf (patch)
treeca1007851ca05a7f3fbd6936f6f10edffd6f2e3b /OvmfPkg/Csm
parent09bb585cb2a9d182e4f15cdd0ab020b3b82ead8a (diff)
downloadedk2-8016da21b56d5ab1da855037cd0f0e034e2404bf.tar.gz
edk2-8016da21b56d5ab1da855037cd0f0e034e2404bf.tar.bz2
edk2-8016da21b56d5ab1da855037cd0f0e034e2404bf.zip
OvmfPkg: Add CsmSupportLib
This library installs the legacy interrupt, region and platform support required for CSM support drivers. Signed-off-by: jljusten Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12681 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'OvmfPkg/Csm')
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.c38
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.h55
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf54
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c196
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.h119
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c1066
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.h104
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c466
-rw-r--r--OvmfPkg/Csm/CsmSupportLib/LegacyRegion.h219
9 files changed, 2317 insertions, 0 deletions
diff --git a/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.c b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.c
new file mode 100644
index 0000000000..c0b0252b9c
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.c
@@ -0,0 +1,38 @@
+/** @file
+ Platform CSM Support Library
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CsmSupportLib.h"
+
+/**
+ The constructor function for the platform CSM support library
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+CsmSupportLibConstructor (
+ VOID
+ )
+{
+ LegacyRegionInit ();
+
+ LegacyInterruptInstall ();
+
+ LegacyBiosPlatformInstall ();
+
+ return EFI_SUCCESS;
+}
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.h b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.h
new file mode 100644
index 0000000000..e3b6e8c628
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.h
@@ -0,0 +1,55 @@
+/** @file
+ Platform CSM Support Library
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CSM_SUPPORT_LIB_H_
+#define _CSM_SUPPORT_LIB_H_
+
+#include <Uefi.h>
+
+/**
+ Initialize Legacy Region support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyRegionInit (
+ VOID
+ );
+
+/**
+ Initialize Legacy Interrupt support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ );
+
+/**
+ Initialize Legacy Platform support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyBiosPlatformInstall (
+ VOID
+ );
+
+#endif
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf
new file mode 100644
index 0000000000..34cadb2b65
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Platform CSM Support Library
+#
+# Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CsmSupportLib
+ FILE_GUID = 04e03541-4663-417d-93f6-976378247d61
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CsmSupportLib
+
+ CONSTRUCTOR = CsmSupportLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CsmSupportLib.c
+ LegacyInterrupt.c
+ LegacyRegion.c
+ LegacyPlatform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDiskInfoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosPlatformProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyInterruptProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiLegacyRegion2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[LibraryClasses]
+ BaseLib
+ PciLib
+ IoLib
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c b/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
new file mode 100644
index 0000000000..cd984174ab
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
@@ -0,0 +1,196 @@
+/** @file
+ Legacy Interrupt Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyInterrupt.h"
+
+//
+// Handle for the Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_HANDLE mLegacyInterruptHandle = NULL;
+
+//
+// The Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {
+ GetNumberPirqs,
+ GetLocation,
+ ReadPirq,
+ WritePirq
+};
+
+STATIC UINT8 PirqReg[MAX_PIRQ_NUMBER] = { PIRQA, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH };
+
+
+/**
+ Return the number of PIRQs supported by this chipset.
+
+ @param[in] This Pointer to LegacyInterrupt Protocol
+ @param[out] NumberPirqs The pointer to return the max IRQ number supported
+
+ @retval EFI_SUCCESS Max PIRQs successfully returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ )
+{
+ *NumberPirqs = MAX_PIRQ_NUMBER;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return PCI location of this device.
+ $PIR table requires this info.
+
+ @param[in] This - Protocol instance pointer.
+ @param[out] Bus - PCI Bus
+ @param[out] Device - PCI Device
+ @param[out] Function - PCI Function
+
+ @retval EFI_SUCCESS Bus/Device/Function returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ )
+{
+ *Bus = LEGACY_INT_BUS;
+ *Device = LEGACY_INT_DEV;
+ *Function = LEGACY_INT_FUNC;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Builds the PCI configuration address for the register specified by PirqNumber
+
+ @param[in] PirqNumber - The PIRQ number to build the PCI configuration address for
+
+ @return The PCI Configuration address for the PIRQ
+**/
+UINTN
+GetAddress (
+ UINT8 PirqNumber
+ )
+{
+ return PCI_LIB_ADDRESS(
+ LEGACY_INT_BUS,
+ LEGACY_INT_DEV,
+ LEGACY_INT_FUNC,
+ PirqReg[PirqNumber]
+ );
+}
+
+/**
+ Read the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value read
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PirqData = PciRead8 (GetAddress (PirqNumber));
+ *PirqData = (UINT8) (*PirqData & 0x7f);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value to write
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciWrite8 (GetAddress (PirqNumber), PirqData);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Legacy Interrupt support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Legacy Interrupt Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiLegacyInterruptProtocolGuid);
+
+ //
+ // Make a new handle and install the protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mLegacyInterruptHandle,
+ &gEfiLegacyInterruptProtocolGuid,
+ &mLegacyInterrupt,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.h b/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.h
new file mode 100644
index 0000000000..193e48bad2
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.h
@@ -0,0 +1,119 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LEGACY_INTERRUPT_H_
+#define _LEGACY_INTERRUPT_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/LegacyInterrupt.h>
+
+#include <Library/PciLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define LEGACY_INT_BUS 0
+#define LEGACY_INT_DEV 1
+#define LEGACY_INT_FUNC 0
+
+#define PIRQN 0x00 // PIRQ Null
+#define PIRQA 0x60
+#define PIRQB 0x61
+#define PIRQC 0x62
+#define PIRQD 0x63
+#define PIRQE 0x68
+#define PIRQF 0x69
+#define PIRQG 0x6A
+#define PIRQH 0x6B
+
+#define MAX_PIRQ_NUMBER 8
+
+/**
+ Return the number of PIRQs supported by this chipset.
+
+ @param[in] This Pointer to LegacyInterrupt Protocol
+ @param[out] NumberPirqs The pointer to return the max IRQ number supported
+
+ @retval EFI_SUCCESS Max PIRQs successfully returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ );
+
+/**
+ Return PCI location of this device.
+ $PIR table requires this info.
+
+ @param[in] This - Protocol instance pointer.
+ @param[out] Bus - PCI Bus
+ @param[out] Device - PCI Device
+ @param[out] Function - PCI Function
+
+ @retval EFI_SUCCESS Bus/Device/Function returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ );
+
+/**
+ Read the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value read
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ );
+
+/**
+ Write the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value to write
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ );
+
+#endif
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c b/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c
new file mode 100644
index 0000000000..af8896ae90
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c
@@ -0,0 +1,1066 @@
+/** @file
+ Legacy BIOS Platform support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyPlatform.h"
+
+EFI_SETUP_BBS_MAP mSetupBbsMap[] = {
+ { 1, 2, 1, 1 }, // ATA HardDrive
+ { 2, 3, 1, 1 }, // ATAPI CDROM
+ { 3, 0x80, 2, 0 }, // PXE
+ { 4, 1, 0, 6 }, // USB Floppy
+ { 4, 2, 0, 6 }, // USB HDD
+ { 4, 3, 0, 6 }, // USB CD
+ { 4, 1, 0, 0 }, // USB ZIP Bugbug since Class/SubClass code is uninitialized
+ { 4, 2, 0, 0 } // USB ZIP Bugbug since Class/SubClass code is uninitialized
+};
+
+//
+// Global variables for System ROMs
+//
+#define SYSTEM_ROM_FILE_GUID \
+{ 0x1547B4F3, 0x3E8A, 0x4FEF, 0x81, 0xC8, 0x32, 0x8E, 0xD6, 0x47, 0xAB, 0x1A }
+
+#define NULL_ROM_FILE_GUID \
+{ 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+SYSTEM_ROM_TABLE mSystemRomTable[] = {
+ { SYSTEM_ROM_FILE_GUID, 1 },
+ { NULL_ROM_FILE_GUID, 0 }
+};
+
+EFI_HANDLE mVgaHandles[0x20];
+EFI_HANDLE mDiskHandles[0x20];
+EFI_HANDLE mIsaHandles[0x20];
+
+EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY IrqPriorityTable[MAX_IRQ_PRIORITY_ENTRIES] = {
+ {0x0B,0},
+ {0x09,0},
+ {0x0A,0},
+ {0x05,0},
+ {0x07,0},
+ {0x00,0},
+ {0x00,0}
+};
+
+//
+// PIRQ Table
+// - Slot numbering will be used to update the bus number and determine bridge
+// to check to get bus number. The Slot number - 1 is an index into a decode
+// table to get the bridge information.
+//
+EFI_LEGACY_PIRQ_TABLE PirqTableHead = {
+ {
+ EFI_LEGACY_PIRQ_TABLE_SIGNATURE, // UINT32 Signature
+ 0x00, // UINT8 MinorVersion
+ 0x01, // UINT8 MajorVersion
+ 0x0000, // UINT16 TableSize
+ 0x00, // UINT8 Bus
+ 0x08, // UINT8 DevFun
+ 0x0000, // UINT16 PciOnlyIrq
+ 0x8086, // UINT16 CompatibleVid
+ 0x122e, // UINT16 CompatibleDid
+ 0x00000000, // UINT32 Miniport
+ { // UINT8 Reserved[11]
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00
+ },
+ 0x00, // UINT8 Checksum
+ },
+ {
+ // -- Pin 1 -- -- Pin 2 -- -- Pin 3 -- -- Pin 4 --
+ // Bus Dev Reg Map Reg Map Reg Map Reg Map
+
+ 0x00,0x08,0x60,0xDEB8,0x61,0xDEB8,0x62,0xDEB8,0x63,0xDEB8,0x00,0x00,
+ 0x00,0x10,0x61,0xDEB8,0x62,0xDEB8,0x63,0xDEB8,0x60,0xDEB8,0x01,0x00,
+ 0x00,0x18,0x62,0xDEB8,0x63,0xDEB8,0x60,0xDEB8,0x61,0xDEB8,0x02,0x00,
+ 0x00,0x20,0x63,0xDEB8,0x60,0xDEB8,0x61,0xDEB8,0x62,0xDEB8,0x03,0x00,
+ 0x00,0x28,0x60,0xDEB8,0x61,0xDEB8,0x62,0xDEB8,0x63,0xDEB8,0x04,0x00,
+ 0x00,0x30,0x61,0xDEB8,0x62,0xDEB8,0x63,0xDEB8,0x60,0xDEB8,0x05,0x00,
+ }
+};
+
+LEGACY_BIOS_PLATFORM_INSTANCE mPrivateData;
+EFI_HANDLE mImageHandle = NULL;
+
+/**
+ Return the handles and assorted information for the specified PCI Class code
+
+ @param[in] PciClasses Array of PCI_CLASS_RECORD to find terminated with ClassCode 0xff
+ @param[in,out] DeviceTable Table to place handles etc in.
+ @param[in,out] DeviceIndex Number of devices found
+ @param[in] DeviceFlags FALSE if a valid legacy ROM is required, TRUE otherwise.
+
+ @retval EFI_SUCCESS One or more devices found
+ @retval EFI_NOT_FOUND No device found
+
+**/
+EFI_STATUS
+FindAllDeviceTypes (
+ IN PCI_CLASS_RECORD *PciClasses,
+ IN OUT DEVICE_STRUCTURE *DeviceTable,
+ IN OUT UINT16 *DeviceIndex,
+ IN BOOLEAN DeviceFlags
+ )
+{
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ UINTN StartIndex;
+ PCI_TYPE00 PciConfigHeader;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Flags;
+ EFI_STATUS Status;
+ UINTN Index2;
+
+ //
+ // Get legacy BIOS protocol as it is required to deal with Option ROMs.
+ //
+ StartIndex = *DeviceIndex;
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get all PCI handles and check them to generate a list of matching devices.
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo
+ );
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciConfigHeader) / sizeof (UINT32),
+ &PciConfigHeader
+ );
+ for (Index2 = 0; PciClasses[Index2].Class != 0xff; Index2++) {
+ if ((PciConfigHeader.Hdr.ClassCode[2] == PciClasses[Index2].Class) &&
+ (PciConfigHeader.Hdr.ClassCode[1] == PciClasses[Index2].SubClass)) {
+ LegacyBios->CheckPciRom (
+ LegacyBios,
+ HandleBuffer[Index],
+ NULL,
+ NULL,
+ &Flags
+ );
+
+ //
+ // Verify that results of OPROM check match request.
+ // The two valid requests are:
+ // DeviceFlags = 0 require a valid legacy ROM
+ // DeviceFlags = 1 require either no ROM or a valid legacy ROM
+ //
+ if (
+ ((DeviceFlags != 0) && (Flags == NO_ROM)) ||
+ ((Flags & (ROM_FOUND | VALID_LEGACY_ROM)) == (ROM_FOUND | VALID_LEGACY_ROM))
+ ) {
+ DeviceTable->Handle = HandleBuffer[Index];
+ DeviceTable->Vid = PciConfigHeader.Hdr.VendorId;
+ DeviceTable->Did = PciConfigHeader.Hdr.DeviceId;
+ DeviceTable->SvId = PciConfigHeader.Device.SubsystemVendorID;
+ DeviceTable->SysId = PciConfigHeader.Device.SubsystemID;
+ ++ *DeviceIndex;
+ DeviceTable++;
+ }
+ }
+ }
+ }
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ if (*DeviceIndex != StartIndex) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ Load and initialize the Legacy BIOS SMM handler.
+
+ @param This The protocol instance pointer.
+ @param EfiToLegacy16BootTable A pointer to Legacy16 boot table.
+
+ @retval EFI_SUCCESS SMM code loaded.
+ @retval EFI_DEVICE_ERROR SMM code failed to load
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInit (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN VOID *EfiToLegacy16BootTable
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Finds the device path that should be used as the primary display adapter.
+
+ @param VgaHandle - The handle of the video device
+
+**/
+VOID
+GetSelectedVgaDeviceInfo (
+ OUT EFI_HANDLE *VgaHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINTN SelectedAddress;
+ UINTN CurrentAddress;
+
+ //
+ // Initialize return to 'not found' state
+ //
+ *VgaHandle = NULL;
+
+ //
+ // Initialize variable states. Ths is important for selecting the VGA device
+ // if multiple devices exist behind a single bridge.
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ SelectedAddress = PCI_LIB_ADDRESS(0xff, 0x1f, 0x7, 0);
+
+ //
+ // The bus range to search for a VGA device in.
+ //
+ MinBus = MaxBus = 0;
+
+ //
+ // Start to check all the pci io to find all possible VGA device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID**)&PciIo);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Detemine if this is in the correct bus range.
+ //
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ if (EFI_ERROR(Status) || (Bus < MinBus || Bus > MaxBus)) {
+ continue;
+ }
+
+ //
+ // Read device information.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Make sure the device is a VGA device.
+ //
+ if (!IS_PCI_VGA (&Pci)) {
+ continue;
+ }
+ DEBUG ((EFI_D_INFO,
+ "PCI VGA: 0x%04x:0x%04x\n",
+ Pci.Hdr.VendorId,
+ Pci.Hdr.DeviceId
+ ));
+
+ //
+ // Currently we use the lowest numbered bus/device/function if multiple
+ // devices are found in the target bus range.
+ //
+ CurrentAddress = PCI_LIB_ADDRESS(Bus, Device, Function, 0);
+ if (CurrentAddress < SelectedAddress) {
+ SelectedAddress = CurrentAddress;
+ *VgaHandle = HandleBuffer[Index];
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+}
+
+
+/**
+ Returns a buffer of handles for the requested subfunction.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param Type Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param HandleBuffer Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param HandleCount Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+
+ @retval EFI_SUCCESS Handle is valid.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+ @retval EFI_NOT_FOUND Handle is not known.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformHandle (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_HANDLE_MODE Mode,
+ IN UINT16 Type,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN *HandleCount,
+ OUT VOID **AdditionalData OPTIONAL
+ )
+{
+ DEVICE_STRUCTURE LocalDevice[0x40];
+ UINT32 LocalIndex;
+ UINT32 Index;
+ DEVICE_STRUCTURE TempDevice;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ HDD_INFO *HddInfo;
+ PCI_TYPE00 PciConfigHeader;
+ UINT32 HddIndex;
+ EFI_HANDLE IdeHandle;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ PCI_CLASS_RECORD ClassLists[10];
+ UINTN PriorityIndex;
+
+ static BOOLEAN bConnected = FALSE;
+
+ LocalIndex = 0x00;
+ HddInfo = NULL;
+ HddIndex = 0;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+
+ //
+ // Process mode specific operations
+ //
+ switch (Mode) {
+ case EfiGetPlatformVgaHandle:
+ //
+ // Get the handle for the currently selected VGA device.
+ //
+ GetSelectedVgaDeviceInfo (&mVgaHandles[0]);
+ *HandleBuffer = &mVgaHandles[0];
+ *HandleCount = (mVgaHandles[0] != NULL) ? 1 : 0;
+ return EFI_SUCCESS;
+ case EfiGetPlatformIdeHandle:
+ IdeHandle = NULL;
+ if (AdditionalData != NULL) {
+ HddInfo = (HDD_INFO *) *AdditionalData;
+ }
+
+ //
+ // Locate all found block io devices
+ //
+ ClassLists[0].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[0].SubClass = PCI_CLASS_MASS_STORAGE_SCSI;
+ ClassLists[1].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[1].SubClass = PCI_CLASS_MASS_STORAGE_IDE;
+ ClassLists[2].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[2].SubClass = PCI_CLASS_MASS_STORAGE_RAID;
+ ClassLists[3].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[3].SubClass = PCI_CLASS_MASS_STORAGE_SATADPA;
+ ClassLists[4].Class = 0xff;
+ FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) &LocalIndex, TRUE);
+ if (LocalIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure all IDE controllers are connected. This is necessary
+ // in NO_CONFIG_CHANGE boot path to ensure IDE controller is correctly
+ // initialized and all IDE drives are enumerated
+ //
+ if (!bConnected) {
+ for (Index = 0; Index < LocalIndex; Index++) {
+ gBS->ConnectController (LocalDevice[Index].Handle, NULL, NULL, TRUE);
+ }
+ }
+
+ //
+ // Locate onboard controllers.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {
+ if (LocalDevice[Index].Did == V_PIIX4_IDE_DEVICE_ID) {
+ IdeHandle = LocalDevice[Index].Handle;
+ }
+ }
+ }
+
+ //
+ // Set the IDE contorller as primary devices.
+ //
+ PriorityIndex = 0;
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Handle == IdeHandle && PriorityIndex == 0) {
+ TempDevice = LocalDevice[PriorityIndex];
+ LocalDevice[PriorityIndex] = LocalDevice[Index];
+ LocalDevice[Index] = TempDevice;
+ PriorityIndex++;
+ break;
+ }
+ }
+
+ //
+ // Copy over handles and update return values.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ mDiskHandles[Index] = LocalDevice[Index].Handle;
+ }
+ *HandleBuffer = &mDiskHandles[0];
+ *HandleCount = LocalIndex;
+
+ //
+ // We have connected all IDE controllers once. No more needed
+ //
+ bConnected = TRUE;
+
+ //
+ // Log all onboard controllers.
+ //
+ for (Index = 0; (Index < LocalIndex) && (AdditionalData != NULL); Index++) {
+ if ((LocalDevice[Index].Handle != NULL) &&
+ (LocalDevice[Index].Handle == IdeHandle)) {
+ Status = gBS->HandleProtocol (
+ LocalDevice[Index].Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciConfigHeader) / sizeof (UINT32),
+ &PciConfigHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIo->GetLocation (
+ PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Be sure to only fill out correct information based on platform
+ // configureation.
+ //
+ HddInfo[HddIndex].Status |= HDD_PRIMARY;
+ HddInfo[HddIndex].Bus = (UINT32)Bus;
+ HddInfo[HddIndex].Device = (UINT32)Device;
+ HddInfo[HddIndex].Function = (UINT32)Function;
+ HddInfo[HddIndex + 1].Status |= HDD_SECONDARY;
+ HddInfo[HddIndex + 1].Bus = (UINT32)Bus;
+ HddInfo[HddIndex + 1].Device = (UINT32)Device;
+ HddInfo[HddIndex + 1].Function = (UINT32)Function;
+
+ //
+ // Primary controller data
+ //
+ if ((PciConfigHeader.Hdr.ClassCode[0] & 0x01) != 0) {
+ HddInfo[HddIndex].CommandBaseAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[0] & 0xfffc);
+ HddInfo[HddIndex].ControlBaseAddress =
+ (UINT16)((PciConfigHeader.Device.Bar[1] & 0xfffc)+2);
+ HddInfo[HddIndex].BusMasterAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[4] & 0xfffc);
+ HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;
+ } else {
+ HddInfo[HddIndex].HddIrq = 14;
+ HddInfo[HddIndex].CommandBaseAddress = 0x1f0;
+ HddInfo[HddIndex].ControlBaseAddress = 0x3f6;
+ HddInfo[HddIndex].BusMasterAddress = 0;
+ }
+ HddIndex++;
+
+ //
+ // Secondary controller data
+ //
+ if ((PciConfigHeader.Hdr.ClassCode[0] & 0x04) != 0) {
+ HddInfo[HddIndex].CommandBaseAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[2] & 0xfffc);
+ HddInfo[HddIndex].ControlBaseAddress =
+ (UINT16)((PciConfigHeader.Device.Bar[3] & 0xfffc)+2);
+ HddInfo[HddIndex].BusMasterAddress =
+ (UINT16)(HddInfo[HddIndex].BusMasterAddress + 8);
+ HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;
+ } else {
+ HddInfo[HddIndex].HddIrq = 15;
+ HddInfo[HddIndex].CommandBaseAddress = 0x170;
+ HddInfo[HddIndex].ControlBaseAddress = 0x376;
+ HddInfo[HddIndex].BusMasterAddress = 0;
+ }
+ HddIndex++;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+ case EfiGetPlatformIsaBusHandle:
+ ClassLists[0].Class = (UINT8) PCI_CLASS_BRIDGE;
+ ClassLists[0].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA_PDECODE;
+ ClassLists[1].Class = (UINT8) PCI_CLASS_BRIDGE;
+ ClassLists[1].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA;
+ ClassLists[2].Class = 0xff;
+
+ //
+ // Locate all found block io devices
+ //
+ FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) (&LocalIndex), TRUE);
+ if (LocalIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find our ISA bridge.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {
+ TempDevice = LocalDevice[0];
+ LocalDevice[0] = LocalDevice[Index];
+ LocalDevice[Index] = TempDevice;
+ }
+ }
+
+ //
+ // Perform copy and update return values.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ mIsaHandles[Index] = LocalDevice[Index].Handle;
+ }
+ *HandleBuffer = &mIsaHandles[0];
+ *HandleCount = LocalIndex;
+ return EFI_SUCCESS;
+ case EfiGetPlatformUsbHandle:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Allows platform to perform any required action after a LegacyBios operation.
+ Invokes the specific sub function specified by Mode.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param Type Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param DeviceHandle Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param ShadowAddress Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param Compatibility16Table Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+
+ @retval EFI_SUCCESS The operation performed successfully. Mode specific.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformHooks (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_HOOK_MODE Mode,
+ IN UINT16 Type,
+ OUT EFI_HANDLE DeviceHandle, OPTIONAL
+ IN OUT UINTN *Shadowaddress, OPTIONAL
+ IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table, OPTIONAL
+ OUT VOID **AdditionalData OPTIONAL
+ )
+{
+ EFI_IA32_REGISTER_SET Regs;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+
+ switch (Mode) {
+ case EfiPlatformHookPrepareToScanRom:
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x03;
+ Status = LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ return Status;
+ case EfiPlatformHookShadowServiceRoms:
+ return EFI_SUCCESS;
+ case EfiPlatformHookAfterRomInit:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Returns information associated with PCI IRQ routing.
+ This function returns the following information associated with PCI IRQ routing:
+ * An IRQ routing table and number of entries in the table.
+ * The $PIR table and its size.
+ * A list of PCI IRQs and the priority order to assign them.
+
+ @param This The protocol instance pointer.
+ @param RoutingTable The pointer to PCI IRQ Routing table.
+ This location is the $PIR table minus the header.
+ @param RoutingTableEntries The number of entries in table.
+ @param LocalPirqTable $PIR table.
+ @param PirqTableSize $PIR table size.
+ @param LocalIrqPriorityTable A list of interrupts in priority order to assign.
+ @param IrqPriorityTableEntries The number of entries in the priority table.
+
+ @retval EFI_SUCCESS Data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+GetRoutingTable (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ OUT VOID **RoutingTable,
+ OUT UINTN *RoutingTableEntries,
+ OUT VOID **LocalPirqTable, OPTIONAL
+ OUT UINTN *PirqTableSize, OPTIONAL
+ OUT VOID **LocalIrqPriorityTable, OPTIONAL
+ OUT UINTN *IrqPriorityTableEntries OPTIONAL
+ )
+{
+ UINT16 PTableSize;
+ UINT32 Index;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Checksum;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;
+
+ Checksum = 0;
+
+ if (LocalPirqTable != NULL) {
+ PTableSize = sizeof (EFI_LEGACY_PIRQ_TABLE_HEADER) +
+ sizeof (EFI_LEGACY_IRQ_ROUTING_ENTRY) * MAX_IRQ_ROUTING_ENTRIES;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyInterruptProtocolGuid,
+ NULL,
+ (VOID**)&LegacyInterrupt
+ );
+ ASSERT_EFI_ERROR (Status);
+ LegacyInterrupt->GetLocation (
+ LegacyInterrupt,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Update fields in $PIR table header
+ //
+ PirqTableHead.PirqTable.TableSize = PTableSize;
+ PirqTableHead.PirqTable.Bus = Bus;
+ PirqTableHead.PirqTable.DevFun = (UINT8) ((Device << 3) + Function);
+ Ptr = (UINT8 *) (&PirqTableHead);
+
+ //
+ // Calculate checksum.
+ //
+ for (Index = 0; Index < PTableSize; Index++) {
+ Checksum = (UINT8) (Checksum + (UINT8) *Ptr);
+ Ptr += 1;
+ }
+ Checksum = (UINT8) (0x00 - Checksum);
+ PirqTableHead.PirqTable.Checksum = Checksum;
+
+ //
+ // Update return values.
+ //
+ *LocalPirqTable = (VOID *) (&PirqTableHead);
+ *PirqTableSize = PTableSize;
+ }
+
+ //
+ // More items to return.
+ //
+ *RoutingTable = PirqTableHead.IrqRoutingEntry;
+ *RoutingTableEntries = MAX_IRQ_ROUTING_ENTRIES;
+ if (LocalIrqPriorityTable != NULL) {
+ *LocalIrqPriorityTable = IrqPriorityTable;
+ *IrqPriorityTableEntries = MAX_IRQ_PRIORITY_ENTRIES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Finds the binary data or other platform information.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what data to return. See See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Table Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param TableSize Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Location Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Alignment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param LegacySegment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param LegacyOffset Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+
+ @retval EFI_SUCCESS Data returned successfully.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+ @retval EFI_NOT_FOUND Binary image or table not found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformInfo (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_INFO_MODE Mode,
+ OUT VOID **Table,
+ OUT UINTN *TableSize,
+ OUT UINTN *Location,
+ OUT UINTN *Alignment,
+ IN UINT16 LegacySegment,
+ IN UINT16 LegacyOffset
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ switch (Mode) {
+ case EfiGetPlatformBinarySystemRom:
+ //
+ // Loop through table of System rom descriptions
+ //
+ for (Index = 0; mSystemRomTable[Index].Valid != 0; Index++) {
+ Status = GetSectionFromFv (
+ &mSystemRomTable[Index].FileName,
+ EFI_SECTION_RAW,
+ 0,
+ Table,
+ (UINTN *) TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+ case EfiGetPlatformBinaryOem16Data:
+ case EfiGetPlatformBinaryMpTable:
+ case EfiGetPlatformBinaryOemIntData:
+ case EfiGetPlatformBinaryOem32Data:
+ case EfiGetPlatformBinaryTpmBinary:
+ case EfiGetPlatformPciExpressBase:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Translates the given PIRQ accounting for bridge.
+ This function translates the given PIRQ back through all buses, if required,
+ and returns the true PIRQ and associated IRQ.
+
+ @param This The protocol instance pointer.
+ @param PciBus The PCI bus number for this device.
+ @param PciDevice The PCI device number for this device.
+ @param PciFunction The PCI function number for this device.
+ @param Pirq Input is PIRQ reported by device, and output is true PIRQ.
+ @param PciIrq The IRQ already assigned to the PIRQ, or the IRQ to be
+ assigned to the PIRQ.
+
+ @retval EFI_SUCCESS The PIRQ was translated.
+
+**/
+EFI_STATUS
+EFIAPI
+TranslatePirq (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN UINTN PciBus,
+ IN UINTN PciDevice,
+ IN UINTN PciFunction,
+ IN OUT UINT8 *Pirq,
+ OUT UINT8 *PciIrq
+ )
+{
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index1;
+ UINT8 LocalPirq;
+ UINT8 PirqData;
+ UINT8 MatchData;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyInterruptProtocolGuid,
+ NULL,
+ (VOID**)&LegacyInterrupt
+ );
+ ASSERT_EFI_ERROR (Status);
+ LocalPirq = (UINT8) (*Pirq);
+
+ for (Index = 0; Index < MAX_IRQ_ROUTING_ENTRIES; Index++) {
+ if ((PirqTableHead.IrqRoutingEntry[Index].Bus == PciBus) &&
+ (PirqTableHead.IrqRoutingEntry[Index].Device == PciDevice)) {
+ LocalPirq = (UINT8) (PirqTableHead.IrqRoutingEntry[Index].PirqEntry[LocalPirq].Pirq & 0x0f);
+ if (LocalPirq > 4) {
+ LocalPirq -= 4;
+ }
+
+ LegacyInterrupt->ReadPirq (LegacyInterrupt, LocalPirq, &PirqData);
+ MatchData = PCI_UNUSED;
+ while (PirqData == 0) {
+ for (Index1 = 0; Index1 < MAX_IRQ_PRIORITY_ENTRIES; Index1++) {
+ if ((IrqPriorityTable[Index1].Used == MatchData) &&
+ (IrqPriorityTable[Index1].Irq != 0)) {
+ PirqData = IrqPriorityTable[Index1].Irq;
+ IrqPriorityTable[Index1].Used = 0xff;
+ LegacyInterrupt->WritePirq (
+ LegacyInterrupt,
+ LocalPirq,
+ PirqData
+ );
+ break;
+ }
+ }
+
+ if (PirqData == 0) {
+
+ //
+ // No unused interrpts, so start reusing them.
+ //
+ MatchData = (UINT8) (~MatchData);
+ }
+ }
+
+ *PciIrq = PirqData;
+ *Pirq = LocalPirq;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Attempt to legacy boot the BootOption. If the EFI contexted has been
+ compromised this function will not return.
+
+ @param This The protocol instance pointer.
+ @param BbsDevicePath The EFI Device Path from BootXXXX variable.
+ @param BbsTable The Internal BBS table.
+ @param LoadOptionSize The size of LoadOption in size.
+ @param LoadOption The LoadOption from BootXXXX variable
+ @param EfiToLegacy16BootTable A pointer to BootTable structure
+
+ @retval EFI_SUCCESS Ready to boot.
+
+**/
+EFI_STATUS
+EFIAPI
+PrepareToBoot (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,
+ IN VOID *BbsTable,
+ IN UINT32 LoadOptionsSize,
+ IN VOID *LoadOptions,
+ IN VOID *EfiToLegacy16BootTable
+ )
+{
+ BBS_TABLE *LocalBbsTable;
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *Legacy16BootTable;
+ DEVICE_PRODUCER_DATA_HEADER *SioPtr;
+ UINT16 DevicePathType;
+ UINT16 Index;
+ UINT16 Priority;
+
+ //
+ // Initialize values
+ //
+ Priority = 0;
+ Legacy16BootTable = (EFI_TO_COMPATIBILITY16_BOOT_TABLE*) EfiToLegacy16BootTable;
+
+ //
+ // Set how Gate A20 is gated by hardware
+ //
+ SioPtr = &Legacy16BootTable->SioData;
+ SioPtr->Flags.A20Kybd = 1;
+ SioPtr->Flags.A20Port90 = 1;
+ SioPtr->MousePresent = 1;
+
+ LocalBbsTable = BbsTable;
+
+ //
+ // There are 2 cases that must be covered.
+ // Case 1: Booting to a legacy OS - BbsDevicePath is non-NULL.
+ // Case 2: Booting to an EFI aware OS - BbsDevicePath is NULL.
+ // We need to perform the PrepareToBoot function to assign
+ // drive numbers to HDD devices to allow the shell or EFI
+ // to access them.
+ //
+ if (BbsDevicePath != NULL) {
+ DevicePathType = BbsDevicePath->DeviceType;
+ } else {
+ DevicePathType = BBS_HARDDISK;
+ }
+
+ //
+ // Skip the boot devices where priority is set by BDS and set the next one
+ //
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY) &&
+ (LocalBbsTable[Index].BootPriority != BBS_LOWEST_PRIORITY) &&
+ (Priority <= LocalBbsTable[Index].BootPriority)) {
+ Priority = (UINT16) (LocalBbsTable[Index].BootPriority + 1);
+ }
+ }
+
+ switch (DevicePathType) {
+ case BBS_FLOPPY:
+ case BBS_HARDDISK:
+ case BBS_CDROM:
+ case BBS_EMBED_NETWORK:
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].DeviceType == DevicePathType)) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+ break;
+ case BBS_BEV_DEVICE:
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].Class == 01) &&
+ (LocalBbsTable[Index].SubClass == 01)) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+ break;
+ case BBS_USB:
+ case BBS_PCMCIA:
+ case BBS_UNKNOWN:
+ default:
+ break;
+ };
+
+ //
+ // Set priority for rest of devices
+ //
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if (LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Legacy Platform support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyBiosPlatformInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ LEGACY_BIOS_PLATFORM_INSTANCE *Private;
+
+ mImageHandle = gImageHandle;
+ Private = &mPrivateData;
+
+ //
+ // Grab a copy of all the protocols we depend on.
+ //
+ Private->Signature = LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE;
+ Private->LegacyBiosPlatform.GetPlatformInfo = GetPlatformInfo;
+ Private->LegacyBiosPlatform.GetPlatformHandle = GetPlatformHandle;
+ Private->LegacyBiosPlatform.SmmInit = SmmInit;
+ Private->LegacyBiosPlatform.PlatformHooks = PlatformHooks;
+ Private->LegacyBiosPlatform.GetRoutingTable = GetRoutingTable;
+ Private->LegacyBiosPlatform.TranslatePirq = TranslatePirq;
+ Private->LegacyBiosPlatform.PrepareToBoot = PrepareToBoot;
+ Private->ImageHandle = gImageHandle;
+
+ //
+ // Make a new handle and install the protocol
+ //
+ Private->Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Private->Handle,
+ &gEfiLegacyBiosPlatformProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Private->LegacyBiosPlatform
+ );
+ return Status;
+}
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.h b/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.h
new file mode 100644
index 0000000000..a4654a446b
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.h
@@ -0,0 +1,104 @@
+/** @file
+ Legacy BIOS Platform support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef LEGACY_BIOS_PLATFORM_H_
+#define LEGACY_BIOS_PLATFORM_H_
+
+#include <FrameworkDxe.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LegacyInterrupt.h>
+#include <Protocol/LegacyRegion2.h>
+#include <Protocol/LegacyBiosPlatform.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/DiskInfo.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+//
+// PIRQ information constants.
+//
+#define MAX_IRQ_ROUTING_ENTRIES 6
+#define MAX_IRQ_PRIORITY_ENTRIES 7
+
+#define V_INTEL_VENDOR_ID 0x8086
+#define V_PIIX4_IDE_DEVICE_ID 0x7010
+
+//
+// Type declarations
+//
+typedef struct {
+ UINT8 SetupValue;
+ UINT16 DeviceType;
+ UINT8 Class;
+ UINT8 SubClass;
+} EFI_SETUP_BBS_MAP;
+
+typedef struct {
+ UINT8 Class;
+ UINT8 SubClass;
+} PCI_CLASS_RECORD;
+
+typedef struct {
+ EFI_LEGACY_PIRQ_TABLE_HEADER PirqTable;
+ EFI_LEGACY_IRQ_ROUTING_ENTRY IrqRoutingEntry[MAX_IRQ_ROUTING_ENTRIES];
+} EFI_LEGACY_PIRQ_TABLE;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ UINT16 Vid;
+ UINT16 Did;
+ UINT16 SvId;
+ UINT16 SysId;
+} DEVICE_STRUCTURE;
+
+typedef struct {
+ EFI_GUID FileName;
+ UINTN Valid;
+} SYSTEM_ROM_TABLE;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL LegacyBiosPlatform;
+ EFI_HANDLE ImageHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+} LEGACY_BIOS_PLATFORM_INSTANCE;
+
+#define LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE SIGNATURE_32('P','B','I','O')
+
+#define LEGACY_BIOS_PLATFORM_INSTANCE_FROM_THIS(this) \
+ CR (this, \
+ LEGACY_BIOS_PLATFORM_INSTANCE, \
+ LegacyBiosPlatform, \
+ LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE \
+ )
+
+#endif
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c b/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c
new file mode 100644
index 0000000000..44d340be68
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c
@@ -0,0 +1,466 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyRegion.h"
+
+//
+// 440 PAM map.
+//
+// PAM Range Offset Bits Operation
+// =============== ====== ==== ===============================================================
+// 0xC0000-0xC3FFF 0x5a 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xC4000-0xC7FFF 0x5a 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xC8000-0xCBFFF 0x5b 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xCC000-0xCFFFF 0x5b 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD0000-0xD3FFF 0x5c 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD4000-0xD7FFF 0x5c 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD8000-0xDBFFF 0x5d 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xDC000-0xDFFFF 0x5d 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE0000-0xE3FFF 0x5e 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE4000-0xE7FFF 0x5e 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE8000-0xEBFFF 0x5f 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xEC000-0xEFFFF 0x5f 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xF0000-0xFFFFF 0x59 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+//
+STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = {
+ {0xC0000, SIZE_16KB, FALSE, FALSE},
+ {0xC4000, SIZE_16KB, FALSE, FALSE},
+ {0xC8000, SIZE_16KB, FALSE, FALSE},
+ {0xCC000, SIZE_16KB, FALSE, FALSE},
+ {0xD0000, SIZE_16KB, FALSE, FALSE},
+ {0xD4000, SIZE_16KB, FALSE, FALSE},
+ {0xD8000, SIZE_16KB, FALSE, FALSE},
+ {0xDC000, SIZE_16KB, FALSE, FALSE},
+ {0xE0000, SIZE_16KB, FALSE, FALSE},
+ {0xE4000, SIZE_16KB, FALSE, FALSE},
+ {0xE8000, SIZE_16KB, FALSE, FALSE},
+ {0xEC000, SIZE_16KB, FALSE, FALSE},
+ {0xF0000, SIZE_64KB, FALSE, FALSE}
+};
+
+STATIC PAM_REGISTER_VALUE mRegisterValues[] = {
+ {REG_PAM1_OFFSET, 0x01, 0x02},
+ {REG_PAM1_OFFSET, 0x10, 0x20},
+ {REG_PAM2_OFFSET, 0x01, 0x02},
+ {REG_PAM2_OFFSET, 0x10, 0x20},
+ {REG_PAM3_OFFSET, 0x01, 0x02},
+ {REG_PAM3_OFFSET, 0x10, 0x20},
+ {REG_PAM4_OFFSET, 0x01, 0x02},
+ {REG_PAM4_OFFSET, 0x10, 0x20},
+ {REG_PAM5_OFFSET, 0x01, 0x02},
+ {REG_PAM5_OFFSET, 0x10, 0x20},
+ {REG_PAM6_OFFSET, 0x01, 0x02},
+ {REG_PAM6_OFFSET, 0x10, 0x20},
+ {REG_PAM0_OFFSET, 0x10, 0x20}
+};
+
+//
+// Handle used to install the Legacy Region Protocol
+//
+STATIC EFI_HANDLE mHandle = NULL;
+
+//
+// Instance of the Legacy Region Protocol to install into the handle database
+//
+STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {
+ LegacyRegion2Decode,
+ LegacyRegion2Lock,
+ LegacyRegion2BootLock,
+ LegacyRegion2Unlock,
+ LegacyRegionGetInfo
+};
+
+STATIC
+EFI_STATUS
+LegacyRegionManipulationInternal (
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN BOOLEAN *ReadEnable,
+ IN BOOLEAN *WriteEnable,
+ OUT UINT32 *Granularity
+ )
+{
+ UINT32 EndAddress;
+ UINTN Index;
+ UINTN StartIndex;
+
+ //
+ // Validate input parameters.
+ //
+ if (Length == 0 || Granularity == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ EndAddress = Start + Length - 1;
+ if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Loop to find the start PAM.
+ //
+ StartIndex = 0;
+ for (Index = 0; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {
+ if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
+ StartIndex = Index;
+ break;
+ }
+ }
+ ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));
+
+ //
+ // Program PAM until end PAM is encountered
+ //
+ for (Index = StartIndex; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {
+ if (ReadEnable != NULL) {
+ if (*ReadEnable) {
+ PciOr8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ mRegisterValues[Index].ReadEnableData
+ );
+ } else {
+ PciAnd8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ (UINT8) (~mRegisterValues[Index].ReadEnableData)
+ );
+ }
+ }
+ if (WriteEnable != NULL) {
+ if (*WriteEnable) {
+ PciOr8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ mRegisterValues[Index].WriteEnableData
+ );
+ } else {
+ PciAnd8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ (UINT8) (~mRegisterValues[Index].WriteEnableData)
+ );
+ }
+ }
+
+ //
+ // If the end PAM is encountered, record its length as granularity and jump out.
+ //
+ if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
+ *Granularity = mSectionArray[Index].Length;
+ break;
+ }
+ }
+ ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+LegacyRegionGetInfoInternal (
+ OUT UINT32 *DescriptorCount,
+ OUT LEGACY_MEMORY_SECTION_INFO **Descriptor
+ )
+{
+ UINTN Index;
+ UINT8 PamValue;
+
+ //
+ // Check input parameters
+ //
+ if (DescriptorCount == NULL || Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Fill in current status of legacy region.
+ //
+ *DescriptorCount = sizeof(mSectionArray) / sizeof (mSectionArray[0]);
+ for (Index = 0; Index < *DescriptorCount; Index++) {
+ PamValue = PciRead8 (PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset));
+ mSectionArray[Index].ReadEnabled = FALSE;
+ if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) {
+ mSectionArray[Index].ReadEnabled = TRUE;
+ }
+ mSectionArray[Index].WriteEnabled = FALSE;
+ if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) {
+ mSectionArray[Index].WriteEnabled = TRUE;
+ }
+ }
+
+ *Descriptor = mSectionArray;
+ return EFI_SUCCESS;
+}
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ )
+{
+ return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity);
+}
+
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = FALSE;
+ return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = TRUE;
+ return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ )
+{
+ LEGACY_MEMORY_SECTION_INFO *SectionInfo;
+ UINT32 SectionCount;
+ EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray;
+ UINTN Index;
+ UINTN DescriptorIndex;
+
+ //
+ // Get section numbers and information
+ //
+ LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo);
+
+ //
+ // Each section has 3 descriptors, corresponding to readability, writeability, and lock status.
+ //
+ DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3);
+ if (DescriptorArray == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DescriptorIndex = 0;
+ for (Index = 0; Index < SectionCount; Index++) {
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ if (SectionInfo[Index].ReadEnabled) {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded;
+ } else {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded;
+ }
+ DescriptorIndex++;
+
+ //
+ // Create descriptor for writeability, according to lock status
+ //
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ if (SectionInfo[Index].WriteEnabled) {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled;
+ } else {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled;
+ }
+ DescriptorIndex++;
+
+ //
+ // Chipset does not support bootlock.
+ //
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked;
+ DescriptorIndex++;
+ }
+
+ *DescriptorCount = (UINT32) DescriptorIndex;
+ *Descriptor = DescriptorArray;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize Legacy Region support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyRegionInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install the Legacy Region Protocol on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.h b/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.h
new file mode 100644
index 0000000000..805df8656f
--- /dev/null
+++ b/OvmfPkg/Csm/CsmSupportLib/LegacyRegion.h
@@ -0,0 +1,219 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LEGACY_REGION_DXE_H_
+#define _LEGACY_REGION_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/LegacyRegion2.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define PAM_PCI_BUS 0
+#define PAM_PCI_DEV 0
+#define PAM_PCI_FUNC 0
+
+#define REG_PAM0_OFFSET 0x59 // Programmable Attribute Map 0
+#define REG_PAM1_OFFSET 0x5a // Programmable Attribute Map 1
+#define REG_PAM2_OFFSET 0x5b // Programmable Attribute Map 2
+#define REG_PAM3_OFFSET 0x5c // Programmable Attribute Map 3
+#define REG_PAM4_OFFSET 0x5d // Programmable Attribute Map 4
+#define REG_PAM5_OFFSET 0x5e // Programmable Attribute Map 5
+#define REG_PAM6_OFFSET 0x5f // Programmable Attribute Map 6
+
+#define PAM_BASE_ADDRESS 0xc0000
+#define PAM_LIMIT_ADDRESS BASE_1MB
+
+//
+// Describes Legacy Region blocks and status.
+//
+typedef struct {
+ UINT32 Start;
+ UINT32 Length;
+ BOOLEAN ReadEnabled;
+ BOOLEAN WriteEnabled;
+} LEGACY_MEMORY_SECTION_INFO;
+
+//
+// Provides a map of the PAM registers and bits used to set Read/Write access.
+//
+typedef struct {
+ UINT8 PAMRegOffset;
+ UINT8 ReadEnableData;
+ UINT8 WriteEnableData;
+} PAM_REGISTER_VALUE;
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ );
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ );
+
+#endif
+