]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Add CsmSupportLib
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 10 Nov 2011 22:04:19 +0000 (22:04 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 10 Nov 2011 22:04:19 +0000 (22:04 +0000)
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

12 files changed:
OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.c [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.h [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.h [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.c [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyPlatform.h [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c [new file with mode: 0644]
OvmfPkg/Csm/CsmSupportLib/LegacyRegion.h [new file with mode: 0644]
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc

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