Browse Source

SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg

Add AcpiTable, Logo image, DEC file and GOP driver.

The iASL build version tested for ACPI table build is 20190816.

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
Reviewed-by: Michael Kubacki <michael.a.kubacki@intel.com>
Wei, David Y 4 years ago
parent
commit
88fdbc3a87
23 changed files with 7305 additions and 0 deletions
  1. 31 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
  2. 821 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
  3. 1579 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
  4. 45 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
  5. 105 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
  6. 84 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
  7. 359 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
  8. 78 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
  9. 46 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
  10. 75 0
      Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
  11. BIN
      Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
  12. 152 0
      Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
  13. 205 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
  14. 1011 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
  15. 15 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
  16. 416 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
  17. 341 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
  18. 507 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
  19. 74 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
  20. 279 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
  21. 302 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
  22. 701 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
  23. 79 0
      Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh

+ 31 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf

@@ -0,0 +1,31 @@
+## @file
+#  Component description file for PlatformAcpiTables module.
+#
+#  ACPI table data and ASL sources required to boot the platform.
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformAcpiTables
+  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+  MODULE_TYPE                    = USER_DEFINED
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  Platform.h
+  Dsdt.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+

+ 821 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl

@@ -0,0 +1,821 @@
+/** @file
+  Contains root level name space objects for the platform
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock ("Dsdt.aml", "DSDT", 1, "INTEL ", "SIMICS  ", 4) {
+  //
+  // System Sleep States
+  //
+  Name (\_S3, Package () {5, 5, 0, 0})
+  Name (\_S4, Package () {6, 6, 0, 0})
+  Name (\_S5, Package () {7, 7, 0, 0})
+
+  Name (GPIC, Zero)
+  Method (_PIC, 1, NotSerialized)  // _PIC: Interrupt Model
+  {
+      GPIC = Arg0
+  }
+  //
+  //  System Bus
+  //
+  Scope (\_SB) {
+    //
+    // PCI Root Bridge
+    //
+    Device (PCI0) {
+      Name (_HID, EISAID ("PNP0A03"))
+      Name (_ADR, 0x00000000)
+      Name (_BBN, 0x00)
+      Name (_UID, 0x00)
+
+
+      // Current resource settings
+      Name (_CRS, ResourceTemplate () {
+        WORDBusNumber (          // Bus number resource (0); the bridge produces bus numbers for its subsequent buses
+          ResourceProducer,      // bit 0 of general flags is 1
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,             // PosDecode
+          0x0000,                // Granularity
+          0x0000,                // Min
+          0x00FF,                // Max
+          0x0000,                // Translation
+          0x0100                 // Range Length = Max-Min+1
+          )
+
+        IO (Decode16, 0xCF8, 0xCF8, 0x01, 0x08)       //Consumed resource (0xCF8-0xCFF)
+
+        WORDIO (                 // Consumed-and-produced resource (all I/O below CF8)
+          ResourceProducer,      // bit 0 of general flags is 0
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,
+          EntireRange,
+          0x0000,                // Granularity
+          0x0000,                // Min
+          0x0CF7,                // Max
+          0x0000,                // Translation
+          0x0CF8                 // Range Length
+          )
+
+        WORDIO (                 // Consumed-and-produced resource (all I/O above CFF)
+          ResourceProducer,      // bit 0 of general flags is 0
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,
+          EntireRange,
+          0x0000,                // Granularity
+          0x0D00,                // Min
+          0xFFFF,                // Max
+          0x0000,                // Translation
+          0xF300                 // Range Length
+          )
+
+        DWORDMEMORY (            // Descriptor for legacy VGA video RAM
+          ResourceProducer,      // bit 0 of general flags is 0
+          PosDecode,
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is Fixed
+          Cacheable,
+          ReadWrite,
+          0x00000000,            // Granularity
+          0x000A0000,            // Min
+          0x000BFFFF,            // Max
+          0x00000000,            // Translation
+          0x00020000             // Range Length
+          )
+
+        DWORDMEMORY (            // Descriptor for 32-bit MMIO
+          ResourceProducer,      // bit 0 of general flags is 0
+          PosDecode,
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is Fixed
+          NonCacheable,
+          ReadWrite,
+          0x00000000,            // Granularity
+          0xF0000000,            // Min
+          0xFBFFFFFF,            // Max
+          0x00000000,            // Translation
+          0x0C000000,            // Range Length
+          ,                      // ResourceSourceIndex
+          ,                      // ResourceSource
+          PW32                   // DescriptorName
+          )
+      })
+
+      //
+      // PCI Interrupt Routing Table - PIC Mode Only
+      //
+      // If you change the IRQ mapping here you also need
+      // to change the mapping in the south bridge
+      // (pci-conf.py) and in the BIOS.
+      // INTA -> 0xa (10)
+      // INTB -> 0xb (11)
+      // INTC -> 0xa (10)
+      // INTD -> 0xb (11)
+
+       Method (_PRT, 0, NotSerialized) {
+           If (GPIC) {
+             Return (AR00) // APIC Mode
+           }
+           Return (PR00) // PIC Mode
+      }
+
+      Name (PR00, Package(){
+            Package () {0x000FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            //
+            // Bus 0, Device 1
+            //
+            Package () {0x0001FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0002FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0002FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0002FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0002FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+            //
+            // Bus 0, Device 3
+            //
+            Package () {0x0003FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0003FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0003FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0003FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0004FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0004FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0004FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0004FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0005FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0005FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0005FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0005FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0006FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0006FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0006FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0006FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0007FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0007FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0007FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0007FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0008FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0008FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0008FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0008FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0009FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0009FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0009FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0009FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00010FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00010FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00010FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00010FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00011FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00011FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00011FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00011FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00012FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00012FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00012FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00012FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00013FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00013FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00013FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00013FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00014FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00014FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00014FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00014FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00015FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00015FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00015FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00015FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00016FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00016FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00016FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00016FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00017FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00017FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00017FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00017FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00018FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00018FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00018FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00018FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00019FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00019FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00019FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00019FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+          }
+        )
+
+      Name(AR00, Package(){
+
+            Package () {0x000FFFF, 0x00, 0, 16},
+            Package () {0x000FFFF, 0x01, 0, 17},
+            Package () {0x000FFFF, 0x02, 0, 18},
+            Package () {0x000FFFF, 0x03, 0, 19},
+
+            //
+            // Bus 0, Device 1
+            //
+            Package () {0x0001FFFF, 0x00, 0, 16},
+            Package () {0x0001FFFF, 0x01, 0, 17},
+            Package () {0x0001FFFF, 0x02, 0, 18},
+            Package () {0x0001FFFF, 0x03, 0, 19},
+
+            Package () {0x0002FFFF, 0x00, 0, 16},
+            Package () {0x0002FFFF, 0x01, 0, 17},
+            Package () {0x0002FFFF, 0x02, 0, 18},
+            Package () {0x0002FFFF, 0x03, 0, 19},
+            //
+            // Bus 0, Device 3
+            //
+            Package () {0x0003FFFF, 0x00, 0, 16},
+            Package () {0x0003FFFF, 0x01, 0, 17},
+            Package () {0x0003FFFF, 0x02, 0, 18},
+            Package () {0x0003FFFF, 0x03, 0, 19},
+
+            Package () {0x0004FFFF, 0x00, 0, 16},
+            Package () {0x0004FFFF, 0x01, 0, 17},
+            Package () {0x0004FFFF, 0x02, 0, 18},
+            Package () {0x0004FFFF, 0x03, 0, 19},
+
+            Package () {0x0005FFFF, 0x00, 0, 16},
+            Package () {0x0005FFFF, 0x01, 0, 17},
+            Package () {0x0005FFFF, 0x02, 0, 18},
+            Package () {0x0005FFFF, 0x03, 0, 19},
+
+            Package () {0x0006FFFF, 0x00, 0, 16},
+            Package () {0x0006FFFF, 0x01, 0, 17},
+            Package () {0x0006FFFF, 0x02, 0, 18},
+            Package () {0x0006FFFF, 0x03, 0, 19},
+
+            Package () {0x0007FFFF, 0x00, 0, 16},
+            Package () {0x0007FFFF, 0x01, 0, 17},
+            Package () {0x0007FFFF, 0x02, 0, 18},
+            Package () {0x0007FFFF, 0x03, 0, 19},
+
+            Package () {0x0008FFFF, 0x00, 0, 16},
+            Package () {0x0008FFFF, 0x01, 0, 17},
+            Package () {0x0008FFFF, 0x02, 0, 18},
+            Package () {0x0008FFFF, 0x03, 0, 19},
+
+            Package () {0x0009FFFF, 0x00, 0, 16},
+            Package () {0x0009FFFF, 0x01, 0, 17},
+            Package () {0x0009FFFF, 0x02, 0, 18},
+            Package () {0x0009FFFF, 0x03, 0, 19},
+
+            Package () {0x000AFFFF, 0x00, 0, 16},
+            Package () {0x000AFFFF, 0x01, 0, 17},
+            Package () {0x000AFFFF, 0x02, 0, 18},
+            Package () {0x000AFFFF, 0x03, 0, 19},
+
+            Package () {0x000BFFFF, 0x00, 0, 16},
+            Package () {0x000BFFFF, 0x01, 0, 17},
+            Package () {0x000BFFFF, 0x02, 0, 18},
+            Package () {0x000BFFFF, 0x03, 0, 19},
+
+            Package () {0x000CFFFF, 0x00, 0, 16},
+            Package () {0x000CFFFF, 0x01, 0, 17},
+            Package () {0x000CFFFF, 0x02, 0, 18},
+            Package () {0x000CFFFF, 0x03, 0, 19},
+
+            Package () {0x000DFFFF, 0x00, 0, 16},
+            Package () {0x000DFFFF, 0x01, 0, 17},
+            Package () {0x000DFFFF, 0x02, 0, 18},
+            Package () {0x000DFFFF, 0x03, 0, 19},
+
+            Package () {0x000EFFFF, 0x00, 0, 16},
+            Package () {0x000EFFFF, 0x01, 0, 17},
+            Package () {0x000EFFFF, 0x02, 0C, 18},
+            Package () {0x000EFFFF, 0x03, 0, 19},
+
+            Package () {0x000FFFFF, 0x00, 0, 16},
+            Package () {0x000FFFFF, 0x01, 0, 17},
+            Package () {0x000FFFFF, 0x02, 0, 18},
+            Package () {0x000FFFFF, 0x03, 0, 19},
+
+            Package () {0x00010FFFF, 0x00, 0, 16},
+            Package () {0x00010FFFF, 0x01, 0, 17},
+            Package () {0x00010FFFF, 0x02, 0, 18},
+            Package () {0x00010FFFF, 0x03, 0, 19},
+
+            Package () {0x00011FFFF, 0x00, 0, 16},
+            Package () {0x00011FFFF, 0x01, 0, 17},
+            Package () {0x00011FFFF, 0x02, 0, 18},
+            Package () {0x00011FFFF, 0x03, 0, 19},
+
+            Package () {0x00012FFFF, 0x00, 0, 16},
+            Package () {0x00012FFFF, 0x01, 0, 17},
+            Package () {0x00012FFFF, 0x02, 0, 18},
+            Package () {0x00012FFFF, 0x03, 0, 19},
+
+            Package () {0x00013FFFF, 0x00, 0, 16},
+            Package () {0x00013FFFF, 0x01, 0, 17},
+            Package () {0x00013FFFF, 0x02, 0, 18},
+            Package () {0x00013FFFF, 0x03, 0, 19},
+
+            Package () {0x00014FFFF, 0x00, 0, 16},
+            Package () {0x00014FFFF, 0x01, 0, 17},
+            Package () {0x00014FFFF, 0x02, 0, 18},
+            Package () {0x00014FFFF, 0x03, 0, 19},
+
+            Package () {0x00015FFFF, 0x00, 0, 16},
+            Package () {0x00015FFFF, 0x01, 0, 17},
+            Package () {0x00015FFFF, 0x02, 0, 18},
+            Package () {0x00015FFFF, 0x03, 0, 19},
+
+            Package () {0x00016FFFF, 0x00, 0, 16},
+            Package () {0x00016FFFF, 0x01, 0, 17},
+            Package () {0x00016FFFF, 0x02, 0, 18},
+            Package () {0x00016FFFF, 0x03, 0, 19},
+
+            Package () {0x00017FFFF, 0x00, 0, 16},
+            Package () {0x00017FFFF, 0x01, 0, 17},
+            Package () {0x00017FFFF, 0x02, 0, 18},
+            Package () {0x00017FFFF, 0x03, 0, 19},
+
+            Package () {0x00018FFFF, 0x00, 0, 16},
+            Package () {0x00018FFFF, 0x01, 0, 17},
+            Package () {0x00018FFFF, 0x02, 0, 18},
+            Package () {0x00018FFFF, 0x03, 0, 19},
+
+            Package () {0x0001EFFFF, 0x00, 0, 16},
+            Package () {0x0001EFFFF, 0x01, 0, 17},
+            Package () {0x0001EFFFF, 0x02, 0, 18},
+            Package () {0x0001EFFFF, 0x03, 0, 19},
+
+            Package () {0x00019FFFF, 0x00, 0, 16},
+            Package () {0x00019FFFF, 0x01, 0, 17},
+            Package () {0x00019FFFF, 0x02, 0, 18},
+            Package () {0x00019FFFF, 0x03, 0, 19},
+
+            Package () {0x0001AFFFF, 0x00, 0, 16},
+            Package () {0x0001AFFFF, 0x01, 0, 17},
+            Package () {0x0001AFFFF, 0x02, 0, 18},
+            Package () {0x0001AFFFF, 0x03, 0, 19},
+
+            Package () {0x0001BFFFF, 0x00, 0, 16},
+            Package () {0x0001BFFFF, 0x01, 0, 17},
+            Package () {0x0001BFFFF, 0x02, 0, 18},
+            Package () {0x0001BFFFF, 0x03, 0, 19},
+
+            Package () {0x0001CFFFF, 0x00, 0, 16},
+            Package () {0x0001CFFFF, 0x01, 0, 17},
+            Package () {0x0001CFFFF, 0x02, 0, 18},
+            Package () {0x0001CFFFF, 0x03, 0, 19},
+
+            Package () {0x0001DFFFF, 0x00, 0, 16},
+            Package () {0x0001DFFFF, 0x01, 0, 17},
+            Package () {0x0001DFFFF, 0x02, 0, 18},
+            Package () {0x0001DFFFF, 0x03, 0, 19},
+
+            Package () {0x0001FFFFF, 0x00, 0, 16},
+            Package () {0x0001FFFFF, 0x01, 0, 17},
+            Package () {0x0001FFFFF, 0x02, 0, 18},
+            Package () {0x0001FFFFF, 0x03, 0, 19},
+          }
+        )
+
+      //
+      // PCI to ISA Bridge (Bus 0, Device 7, Function 0)
+      //
+      Device (LPC) {
+        Name (_ADR, 0x001F0000)
+
+        //
+        // PCI Interrupt Routing Configuration Registers
+        //
+        OperationRegion (PRR0, PCI_Config, 0x60, 0x0C)
+        Field (PRR0, ANYACC, NOLOCK, PRESERVE) {
+          PIRA, 8,
+          PIRB, 8,
+          PIRC, 8,
+          PIRD, 8,
+          Offset (0x04),
+          PIRE, 8,
+          PIRF, 8,
+          PIRG, 8,
+          PIRH, 8
+        }
+
+        //
+        // _STA method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PSTA, 1, NotSerialized) {
+          If (And (Arg0, 0x80)) {
+            Return (0x9)
+          } Else {
+            Return (0xB)
+          }
+        }
+
+        //
+        // _DIS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PDIS, 1, NotSerialized) {
+          Or (Arg0, 0x80, Arg0)
+        }
+
+        //
+        // _CRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PCRS, 1, NotSerialized) {
+          Name (BUF0, ResourceTemplate () {IRQ (Level, ActiveLow, Shared){0}})
+          //
+          // Define references to buffer elements
+          //
+          CreateWordField (BUF0, 0x01, IRQW)  // IRQ low
+          //
+          // Write current settings into IRQ descriptor
+          //
+          If (And (Arg0, 0x80)) {
+            Store (Zero, Local0)
+          } Else {
+            Store (One, Local0)
+          }
+          //
+          // Shift 1 by value in register 70
+          //
+          ShiftLeft (Local0, And (Arg0, 0x0F), IRQW)   // Save in buffer
+          Return (BUF0)                                // Return Buf0
+        }
+
+        //
+        // _PRS resource for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Name (PPRS, ResourceTemplate () {
+          IRQ (Level, ActiveLow, Shared) {3, 4, 5, 7, 9, 10, 11, 12, 14, 15}
+        })
+
+        //
+        // _SRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PSRS, 2, NotSerialized) {
+          CreateWordField (Arg1, 0x01, IRQW)      // IRQ low
+          FindSetRightBit (IRQW, Local0)          // Set IRQ
+          If (LNotEqual (IRQW, Zero)) {
+            And (Local0, 0x7F, Local0)
+            Decrement (Local0)
+          } Else {
+            Or (Local0, 0x80, Local0)
+          }
+          Store (Local0, Arg0)
+        }
+
+        //
+        // PCI IRQ Link A
+        //
+        Device (LNKA) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 1)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRA)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRA)  }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRA)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRA, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link B
+        //
+        Device (LNKB) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 2)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRB)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRB) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRB)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRB, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link C
+        //
+        Device (LNKC) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 3)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRC)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRC) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRC)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRC, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link D
+        //
+        Device (LNKD) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 4)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRD)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRD) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRD)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRD, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link E
+        //
+        Device (LNKE) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 5)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRE)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRE) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRE)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRE, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link F
+        //
+        Device (LNKF) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 6)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRF)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRF) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRF)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRF, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link G
+        //
+        Device (LNKG) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 7)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRG)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRG) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRG)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRG, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link H
+        //
+        Device (LNKH) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 8)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRH)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRH) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRH)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRH, Arg0) }
+        }
+
+        //
+        // Programmable Interrupt Controller (PIC)
+        //
+        Device(PIC) {
+          Name (_HID, EISAID ("PNP0000"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x020, 0x020, 0x00, 0x02)
+            IO (Decode16, 0x0A0, 0x0A0, 0x00, 0x02)
+            IO (Decode16, 0x4D0, 0x4D0, 0x00, 0x02)
+            IRQNoFlags () {2}
+          })
+        }
+
+        //
+        // ISA DMA
+        //
+        Device (DMAC) {
+          Name (_HID, EISAID ("PNP0200"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x00, 0x00, 0, 0x10)
+            IO (Decode16, 0x81, 0x81, 0, 0x03)
+            IO (Decode16, 0x87, 0x87, 0, 0x01)
+            IO (Decode16, 0x89, 0x89, 0, 0x03)
+            IO (Decode16, 0x8f, 0x8f, 0, 0x01)
+            IO (Decode16, 0xc0, 0xc0, 0, 0x20)
+            DMA (Compatibility, NotBusMaster, Transfer8) {4}
+          })
+        }
+
+        //
+        // 8254 Timer
+        //
+        Device(TMR) {
+          Name(_HID,EISAID("PNP0100"))
+          Name(_CRS, ResourceTemplate () {
+            IO (Decode16, 0x40, 0x40, 0x00, 0x04)
+            IRQNoFlags () {0}
+          })
+        }
+
+        //
+        // Real Time Clock
+        //
+        Device (RTC) {
+          Name (_HID, EISAID ("PNP0B00"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x70, 0x70, 0x00, 0x02)
+            IRQNoFlags () {8}
+          })
+        }
+
+        //
+        // PCAT Speaker
+        //
+        Device(SPKR) {
+          Name (_HID, EISAID("PNP0800"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x61, 0x61, 0x01, 0x01)
+          })
+        }
+
+        //
+        // Floating Point Coprocessor
+        //
+        Device(FPU) {
+          Name (_HID, EISAID("PNP0C04"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0xF0, 0xF0, 0x00, 0x10)
+            IRQNoFlags () {13}
+          })
+        }
+
+        //
+        // Generic motherboard devices and pieces that don't fit anywhere else
+        //
+        Device(XTRA) {
+          Name (_HID, EISAID ("PNP0C02"))
+          Name (_UID, 0x01)
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x010, 0x010, 0x00, 0x10)
+            IO (Decode16, 0x022, 0x022, 0x00, 0x1E)
+            IO (Decode16, 0x044, 0x044, 0x00, 0x1C)
+            IO (Decode16, 0x062, 0x062, 0x00, 0x02)
+            IO (Decode16, 0x065, 0x065, 0x00, 0x0B)
+            IO (Decode16, 0x072, 0x072, 0x00, 0x0E)
+            IO (Decode16, 0x080, 0x080, 0x00, 0x01)
+            IO (Decode16, 0x084, 0x084, 0x00, 0x03)
+            IO (Decode16, 0x088, 0x088, 0x00, 0x01)
+            IO (Decode16, 0x08c, 0x08c, 0x00, 0x03)
+            IO (Decode16, 0x090, 0x090, 0x00, 0x10)
+            IO (Decode16, 0x0A2, 0x0A2, 0x00, 0x1E)
+            IO (Decode16, 0x0E0, 0x0E0, 0x00, 0x10)
+            IO (Decode16, 0x1E0, 0x1E0, 0x00, 0x10)
+            IO (Decode16, 0x160, 0x160, 0x00, 0x10)
+            IO (Decode16, 0x278, 0x278, 0x00, 0x08)
+            IO (Decode16, 0x370, 0x370, 0x00, 0x02)
+            IO (Decode16, 0x378, 0x378, 0x00, 0x08)
+            IO (Decode16, 0x400, 0x400, 0x00, 0x40)       // PMBLK1
+            IO (Decode16, 0x440, 0x440, 0x00, 0x10)
+            IO (Decode16, 0x678, 0x678, 0x00, 0x08)
+            IO (Decode16, 0x778, 0x778, 0x00, 0x08)
+            Memory32Fixed (ReadOnly, 0xFEC00000, 0x1000)  // IO APIC
+            Memory32Fixed (ReadOnly, 0xFEE00000, 0x100000) // LAPIC
+          })
+        }
+
+        //
+        // PS/2 Keyboard and PC/AT Enhanced Keyboard 101/102
+        //
+        Device (PS2K) {
+          Name (_HID, EISAID ("PNP0303"))
+          Name (_CID, EISAID ("PNP030B"))
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x60, 0x60, 0x00, 0x01)
+            IO (Decode16, 0x64, 0x64, 0x00, 0x01)
+            IRQNoFlags () {1}
+          })
+        }
+
+        //
+        // PS/2 Mouse and Microsoft Mouse
+        //
+        Device (PS2M) {  // PS/2 stype mouse port
+          Name (_HID, EISAID ("PNP0F03"))
+          Name (_CID, EISAID ("PNP0F13"))
+          Name (_CRS, ResourceTemplate() {
+            IRQNoFlags () {12}
+          })
+        }
+
+        //
+        // UART Serial Port - COM1
+        //
+        Device (UAR1) {
+          Name (_HID, EISAID ("PNP0501"))
+          Name (_DDN, "COM1")
+          Name (_UID, 0x01)
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x3F8, 0x3F8, 0x00, 0x08)
+            IRQ (Edge, ActiveHigh, Exclusive, ) {4}
+          })
+        }
+
+        //
+        // UART Serial Port - COM2
+        //
+        Device (UAR2) {
+          Name (_HID, EISAID ("PNP0501"))
+          Name (_DDN, "COM2")
+          Name (_UID, 0x02)
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x2F8, 0x2F8, 0x00, 0x08)
+            IRQ (Edge, ActiveHigh, Exclusive, ) {3}
+          })
+        }
+      }
+	}
+  }
+}

+ 1579 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c

@@ -0,0 +1,1579 @@
+/** @file
+  ACPI Platform Driver
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatform.h"
+
+#define MAX_CPU_NUM (FixedPcdGet32(PcdMaxCpuThreadCount) * FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuSocketCount))
+
+#pragma pack(1)
+
+typedef struct {
+  UINT32   AcpiProcessorId;
+  UINT32   ApicId;
+  UINT32   Flags;
+  UINT32   SwProcApicId;
+  UINT32   SocketNum;
+} EFI_CPU_ID_ORDER_MAP;
+
+//
+// Private Driver Data
+//
+//
+// Define Union of IO APIC & Local APIC structure;
+//
+typedef union {
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
+  EFI_ACPI_4_0_IO_APIC_STRUCTURE              AcpiIoApic;
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
+  struct {
+    UINT8 Type;
+    UINT8 Length;
+  } AcpiApicCommon;
+} ACPI_APIC_STRUCTURE_PTR;
+
+#pragma pack()
+
+extern EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  Facs;
+extern EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt;
+extern EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER  Hpet;
+extern EFI_ACPI_WSMT_TABLE Wsmt;
+
+VOID  *mLocalTable[] = {
+  &Facs,
+  &Fadt,
+  &Hpet,
+  &Wsmt,
+};
+
+EFI_ACPI_TABLE_PROTOCOL       *mAcpiTable;
+
+UINT32                      mNumOfBitShift = 6;
+BOOLEAN                     mForceX2ApicId;
+BOOLEAN                     mX2ApicEnabled;
+
+EFI_MP_SERVICES_PROTOCOL    *mMpService;
+BOOLEAN                     mCpuOrderSorted;
+EFI_CPU_ID_ORDER_MAP        mCpuApicIdOrderTable[MAX_CPU_NUM];
+UINTN                       mNumberOfCPUs = 0;
+UINTN                       mNumberOfEnabledCPUs = 0;
+//
+// following are possible APICID Map for SKX
+//
+static const UINT32 ApicIdMapA[] = {  //for SKUs have number of core > 16
+  //it is 14 + 14 + 14 + 14 format
+  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x00000010, 0x00000011,
+  0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018, 0x00000019,
+  0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x00000020, 0x00000021, 0x00000022, 0x00000023,
+  0x00000024, 0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002A, 0x0000002B,
+  0x0000002C, 0x0000002D, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035,
+  0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D
+};
+
+static const UINT32 ApicIdMapB[] = { //for SKUs have number of cores <= 16 use 32 ID space
+  //
+  //it is 16+16 format
+  //
+  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+  0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
+  0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+
+static const UINT32 ApicIdMapC[] = { //for SKUs have number of cores <= 16 use 64 ID space
+  //
+  //it is 16+0+16+0 format
+  //
+  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+  0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027,
+  0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static const UINT32 ApicIdMapD[] = { //for SKUs have number of cores <= 8 use 16 ID space
+  //
+  //it is 16 format
+  //
+  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+const UINT32 *mApicIdMap = NULL;
+
+/**
+  This function detect the APICID map and update ApicID Map pointer
+
+  @param None
+
+  @retval VOID
+
+**/
+VOID DetectApicIdMap(VOID)
+{
+  UINTN                  CoreCount;
+
+  CoreCount = 0;
+
+  if(mApicIdMap != NULL) {
+    return;   //aleady initialized
+  }
+
+  mApicIdMap = ApicIdMapA;  // default to > 16C SKUs
+
+  CoreCount = mNumberOfEnabledCPUs / 2;
+  DEBUG ((DEBUG_INFO, "CoreCount - %d\n", CoreCount));
+
+  if(CoreCount <= 16) {
+
+    if(mNumOfBitShift == 4) {
+      mApicIdMap = ApicIdMapD;
+    }
+
+    if(mNumOfBitShift == 5) {
+      mApicIdMap = ApicIdMapB;
+    }
+
+    if(mNumOfBitShift == 6) {
+      mApicIdMap = ApicIdMapC;
+    }
+
+  }
+
+  return;
+}
+
+/**
+  This function return the CoreThreadId of ApicId from ACPI ApicId Map array
+
+  @param ApicId
+
+  @retval Index of ACPI ApicId Map array
+
+**/
+UINT32
+GetIndexFromApicId (
+  UINT32 ApicId
+  )
+{
+  UINT32 CoreThreadId;
+  UINT32 i;
+
+  ASSERT (mApicIdMap != NULL);
+
+  CoreThreadId = ApicId & ((1 << mNumOfBitShift) - 1);
+
+  for(i = 0; i < (FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)); i++) {
+    if(mApicIdMap[i] == CoreThreadId) {
+      break;
+    }
+  }
+
+  ASSERT (i <= (FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)));
+
+  return i;
+}
+
+UINT32
+ApicId2SwProcApicId (
+  UINT32 ApicId
+  )
+{
+  UINT32 Index;
+
+  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+    if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
+      return Index;
+    }
+  }
+
+  return (UINT32) -1;
+
+}
+
+VOID
+DebugDisplayReOrderTable(
+  VOID
+  )
+{
+  UINT32 Index;
+
+  DEBUG ((EFI_D_ERROR, "Index  AcpiProcId  ApicId  Flags  SwApicId  Skt\n"));
+  for (Index=0; Index<MAX_CPU_NUM; Index++) {
+    DEBUG ((EFI_D_ERROR, " %02d       0x%02X      0x%02X      %d      0x%02X     %d\n",
+                           Index, mCpuApicIdOrderTable[Index].AcpiProcessorId,
+                           mCpuApicIdOrderTable[Index].ApicId,
+                           mCpuApicIdOrderTable[Index].Flags,
+                           mCpuApicIdOrderTable[Index].SwProcApicId,
+                           mCpuApicIdOrderTable[Index].SocketNum));
+  }
+}
+
+EFI_STATUS
+AppendCpuMapTableEntry (
+    IN VOID   *ApicPtr,
+    IN UINT32 LocalApicCounter
+  )
+{
+  EFI_STATUS    Status;
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
+  UINT8         Type;
+
+  Status = EFI_SUCCESS;
+  Type = ((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiApicCommon.Type;
+  LocalApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
+  LocalX2ApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
+
+  if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC) {
+    if(!mX2ApicEnabled) {
+      LocalApicPtr->Flags           = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
+      LocalApicPtr->ApicId          = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].ApicId;
+      LocalApicPtr->AcpiProcessorId = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
+    } else {
+      LocalApicPtr->Flags           = 0;
+      LocalApicPtr->ApicId          = 0xFF;
+      LocalApicPtr->AcpiProcessorId = (UINT8)0xFF;
+      Status = EFI_UNSUPPORTED;
+    }
+  } else if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC) {
+    if(mX2ApicEnabled) {
+      LocalX2ApicPtr->Flags            = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
+      LocalX2ApicPtr->X2ApicId         = mCpuApicIdOrderTable[LocalApicCounter].ApicId;
+      LocalX2ApicPtr->AcpiProcessorUid = mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
+    } else {
+      LocalX2ApicPtr->Flags            = 0;
+      LocalX2ApicPtr->X2ApicId         = (UINT32)-1;
+      LocalX2ApicPtr->AcpiProcessorUid = (UINT32)-1;
+      Status = EFI_UNSUPPORTED;
+    }
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+  return Status;
+
+}
+
+EFI_STATUS
+SortCpuLocalApicInTable (
+  VOID
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_PROCESSOR_INFORMATION                 ProcessorInfoBuffer;
+  UINT32                                    Index;
+  UINT32                                    CurrProcessor;
+  UINT32                                    BspApicId;
+  UINT32                                    TempVal = 0;
+  EFI_CPU_ID_ORDER_MAP                      *CpuIdMapPtr;
+  UINT32                                    CoreThreadMask;
+
+  Index      = 0;
+  Status     = EFI_SUCCESS;
+
+  CoreThreadMask = (UINT32) ((1 << mNumOfBitShift) - 1);
+
+  if(!mCpuOrderSorted) {
+
+    Index  = 0;
+
+    for (CurrProcessor = 0; CurrProcessor < mNumberOfCPUs; CurrProcessor++) {
+      Status = mMpService->GetProcessorInfo (
+                                            mMpService,
+                                            CurrProcessor,
+                                            &ProcessorInfoBuffer
+                                            );
+
+      if ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0) {
+        if(ProcessorInfoBuffer.ProcessorId & 1) { //is 2nd thread
+          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[(Index - 1) + MAX_CPU_NUM / 2];
+        } else { //is primary thread
+          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
+          Index++;
+        }
+        CpuIdMapPtr->ApicId  = (UINT32)ProcessorInfoBuffer.ProcessorId;
+        CpuIdMapPtr->Flags   = ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0);
+        CpuIdMapPtr->SocketNum = (UINT32)ProcessorInfoBuffer.Location.Package;
+        CpuIdMapPtr->AcpiProcessorId = (CpuIdMapPtr->SocketNum * FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)) + GetIndexFromApicId(CpuIdMapPtr->ApicId); //CpuIdMapPtr->ApicId;
+        CpuIdMapPtr->SwProcApicId = ((UINT32)(ProcessorInfoBuffer.Location.Package << mNumOfBitShift) + (((UINT32)ProcessorInfoBuffer.ProcessorId) & CoreThreadMask));
+        if(mX2ApicEnabled) { //if X2Apic, re-order the socket # so it starts from base 0 and contiguous
+          //may not necessory!!!!!
+        }
+
+        //update processorbitMask
+        if (CpuIdMapPtr->Flags == 1) {
+
+          if(mForceX2ApicId) {
+            CpuIdMapPtr->SocketNum &= 0x7;
+            CpuIdMapPtr->AcpiProcessorId &= 0xFF; //keep lower 8bit due to use Proc obj in dsdt
+            CpuIdMapPtr->SwProcApicId &= 0xFF;
+          }
+        }
+      } else {  //not enabled
+        CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
+        CpuIdMapPtr->ApicId  = (UINT32)-1;
+        CpuIdMapPtr->Flags   = 0;
+        CpuIdMapPtr->AcpiProcessorId = (UINT32)-1;
+        CpuIdMapPtr->SwProcApicId = (UINT32)-1;
+        CpuIdMapPtr->SocketNum = (UINT32)-1;
+      } //end if PROC ENABLE
+    } //end for CurrentProcessor
+    //
+    //keep for debug purpose
+	//
+    DEBUG(( EFI_D_ERROR, "::ACPI::  APIC ID Order Table Init.   CoreThreadMask = %x,  mNumOfBitShift = %x\n", CoreThreadMask, mNumOfBitShift));
+    DebugDisplayReOrderTable();
+    //
+    //make sure 1st entry is BSP
+	//
+    if(mX2ApicEnabled) {
+      BspApicId = (UINT32)AsmReadMsr64(0x802);
+    } else {
+      BspApicId = (*(volatile UINT32 *)(UINTN)0xFEE00020) >> 24;
+    }
+    DEBUG ((EFI_D_INFO, "BspApicId - 0x%x\n", BspApicId));
+
+    if(mCpuApicIdOrderTable[0].ApicId != BspApicId) {
+      //
+      //check to see if 1st entry is BSP, if not swap it
+	  //
+      Index = ApicId2SwProcApicId(BspApicId);
+
+      if(MAX_CPU_NUM <= Index) {
+        DEBUG ((EFI_D_ERROR, "Asserting the SortCpuLocalApicInTable Index Bufferflow\n"));
+        ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
+      }
+
+      TempVal = mCpuApicIdOrderTable[Index].ApicId;
+      mCpuApicIdOrderTable[Index].ApicId = mCpuApicIdOrderTable[0].ApicId;
+      mCpuApicIdOrderTable[0].ApicId = TempVal;
+      mCpuApicIdOrderTable[Index].Flags = mCpuApicIdOrderTable[0].Flags;
+      mCpuApicIdOrderTable[0].Flags = 1;
+      TempVal = mCpuApicIdOrderTable[Index].SwProcApicId;
+      mCpuApicIdOrderTable[Index].SwProcApicId = mCpuApicIdOrderTable[0].SwProcApicId;
+      mCpuApicIdOrderTable[0].SwProcApicId = TempVal;
+      //
+      //swap AcpiProcId
+	  //
+      TempVal = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+      mCpuApicIdOrderTable[Index].AcpiProcessorId = mCpuApicIdOrderTable[0].AcpiProcessorId;
+      mCpuApicIdOrderTable[0].AcpiProcessorId = TempVal;
+
+    }
+    //
+    //Make sure no holes between enabled threads
+	//
+    for(CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+
+      if(mCpuApicIdOrderTable[CurrProcessor].Flags == 0) {
+        //
+        //make sure disabled entry has ProcId set to FFs
+		//
+        mCpuApicIdOrderTable[CurrProcessor].ApicId = (UINT32)-1;
+        mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (UINT32)-1;
+        mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = (UINT32)-1;
+
+        for(Index = CurrProcessor+1; Index < MAX_CPU_NUM; Index++) {
+          if(mCpuApicIdOrderTable[Index].Flags == 1) {
+            //
+            //move enabled entry up
+			//
+            mCpuApicIdOrderTable[CurrProcessor].Flags = 1;
+            mCpuApicIdOrderTable[CurrProcessor].ApicId = mCpuApicIdOrderTable[Index].ApicId;
+            mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+            mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = mCpuApicIdOrderTable[Index].SwProcApicId;
+            mCpuApicIdOrderTable[CurrProcessor].SocketNum = mCpuApicIdOrderTable[Index].SocketNum;
+            //
+            //disable moved entry
+            //
+            mCpuApicIdOrderTable[Index].Flags = 0;
+            mCpuApicIdOrderTable[Index].ApicId = (UINT32)-1;
+            mCpuApicIdOrderTable[Index].AcpiProcessorId = (UINT32)-1;
+            mCpuApicIdOrderTable[Index].SwProcApicId = (UINT32)-1;
+            break;
+          }
+        }
+      }
+    }
+    //
+    //keep for debug purpose
+    //
+    DEBUG ((EFI_D_ERROR, "APIC ID Order Table ReOrdered\n"));
+    DebugDisplayReOrderTable();
+
+    mCpuOrderSorted = TRUE;
+  }
+
+  return Status;
+}
+
+
+/** Structure of a sub-structure of the ACPI header.
+
+  This structure contains the type and length fields, which are common to every
+  sub-structure of the ACPI tables. A pointer to any structure can be cast as this.
+**/
+typedef struct {
+  UINT8 Type;
+  UINT8 Length;
+} STRUCTURE_HEADER;
+
+STRUCTURE_HEADER mMadtStructureTable[] = {
+  {EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC,          sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE)},
+  {EFI_ACPI_4_0_IO_APIC,                       sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE)},
+  {EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE,     sizeof (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE)},
+  {EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE, sizeof (EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE)},
+  {EFI_ACPI_4_0_LOCAL_APIC_NMI,                sizeof (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE)},
+  {EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE,   sizeof (EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE)},
+  {EFI_ACPI_4_0_IO_SAPIC,                      sizeof (EFI_ACPI_4_0_IO_SAPIC_STRUCTURE)},
+  {EFI_ACPI_4_0_LOCAL_SAPIC,                   sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE)},
+  {EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES,    sizeof (EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE)},
+  {EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC,        sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE)},
+  {EFI_ACPI_4_0_LOCAL_X2APIC_NMI,              sizeof (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE)}
+};
+
+/**
+  Get the size of the ACPI table.
+
+  This function calculates the size needed for the ACPI Table based on the number and
+  size of the sub-structures that will compose it.
+
+  @param[in]  TableSpecificHdrLength  Size of the table specific header, not the ACPI standard header size.
+  @param[in]  Structures              Pointer to an array of sub-structure pointers.
+  @param[in]  StructureCount          Number of structure pointers in the array.
+
+  @return     Total size needed for the ACPI table.
+**/
+UINT32
+GetTableSize (
+  IN  UINTN                 TableSpecificHdrLength,
+  IN  STRUCTURE_HEADER      **Structures,
+  IN  UINTN                 StructureCount
+  )
+{
+  UINT32  TableLength;
+  UINT32  Index;
+
+  //
+  // Compute size of the ACPI table; header plus all structures needed.
+  //
+  TableLength = (UINT32) TableSpecificHdrLength;
+
+  for (Index = 0; Index < StructureCount; Index++) {
+    ASSERT (Structures[Index] != NULL);
+    if (Structures[Index] == NULL) {
+      return 0;
+    }
+
+    TableLength += Structures[Index]->Length;
+  }
+
+  return TableLength;
+}
+
+/**
+  Allocate the ACPI Table.
+
+  This function allocates space for the ACPI table based on the number and size of
+  the sub-structures that will compose it.
+
+  @param[in]  TableSpecificHdrLength  Size of the table specific header, not the ACPI standard header size.
+  @param[in]  Structures  Pointer to an array of sub-structure pointers.
+  @param[in]  StructureCount  Number of structure pointers in the array.
+  @param[out] Table            Newly allocated ACPI Table pointer.
+
+  @retval EFI_SUCCESS           Successfully allocated the Table.
+  @retval EFI_OUT_OF_RESOURCES  Space for the Table could not be allocated.
+**/
+EFI_STATUS
+AllocateTable (
+  IN  UINTN                        TableSpecificHdrLength,
+  IN  STRUCTURE_HEADER             **Structures,
+  IN  UINTN                        StructureCount,
+  OUT EFI_ACPI_DESCRIPTION_HEADER  **Table
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      Size;
+  EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
+
+  //
+  // Get the size of the ACPI table and allocate memory.
+  //
+  Size = GetTableSize (TableSpecificHdrLength, Structures, StructureCount);
+  InternalTable = (EFI_ACPI_DESCRIPTION_HEADER *) AllocatePool (Size);
+
+  if (InternalTable == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "Failed to allocate %d bytes for ACPI Table\n",
+      Size
+      ));
+  } else {
+    Status = EFI_SUCCESS;
+    DEBUG ((
+      DEBUG_INFO,
+      "Successfully allocated %d bytes for ACPI Table at 0x%p\n",
+      Size,
+      InternalTable
+      ));
+    *Table = InternalTable;
+  }
+
+  return Status;
+}
+
+/**
+  Initialize the header.
+
+  This function fills in the standard table header with correct values,
+  except for the length and checksum fields, which are filled in later.
+
+  @param[in,out]  Header        Pointer to the header structure.
+
+  @retval EFI_SUCCESS           Successfully initialized the header.
+  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+**/
+EFI_STATUS
+InitializeHeader (
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER *Header,
+  IN      UINT32                      Signature,
+  IN      UINT8                       Revision,
+  IN      UINT32                      OemRevision
+  )
+{
+  UINT64 AcpiTableOemId;
+
+  if (Header == NULL) {
+    DEBUG ((DEBUG_ERROR, "Header pointer is NULL\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Header->Signature  = Signature;
+  Header->Length     = 0; // filled in by Build function
+  Header->Revision   = Revision;
+  Header->Checksum   = 0; // filled in by InstallAcpiTable
+
+  CopyMem (
+    (VOID *) &Header->OemId,
+    PcdGetPtr (PcdAcpiDefaultOemId),
+    sizeof (Header->OemId)
+    );
+
+  AcpiTableOemId = PcdGet64 (PcdAcpiDefaultOemTableId);
+  CopyMem (
+    (VOID *) &Header->OemTableId,
+    (VOID *) &AcpiTableOemId,
+    sizeof (Header->OemTableId)
+    );
+
+  Header->OemRevision     = OemRevision;
+  Header->CreatorId       = 0;
+  Header->CreatorRevision = 0;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize the MADT header.
+
+  This function fills in the MADT's standard table header with correct values,
+  except for the length and checksum fields, which are filled in later.
+
+  @param[in,out]  MadtHeader    Pointer to the MADT header structure.
+
+  @retval EFI_SUCCESS           Successfully initialized the MADT header.
+  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+**/
+EFI_STATUS
+InitializeMadtHeader (
+  IN OUT EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader
+  )
+{
+  EFI_STATUS Status;
+
+  if (MadtHeader == NULL) {
+    DEBUG ((DEBUG_ERROR, "MADT header pointer is NULL\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = InitializeHeader (
+    &MadtHeader->Header,
+    EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+    EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+    0
+    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  MadtHeader->LocalApicAddress       = PcdGet32(PcdLocalApicAddress);
+  MadtHeader->Flags                  = EFI_ACPI_4_0_PCAT_COMPAT;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Copy an ACPI sub-structure; MADT and SRAT supported
+
+  This function validates the structure type and size of a sub-structure
+  and returns a newly allocated copy of it.
+
+  @param[in]  Header            Pointer to the header of the table.
+  @param[in]  Structure         Pointer to the structure to copy.
+  @param[in]  NewStructure      Newly allocated copy of the structure.
+
+  @retval EFI_SUCCESS           Successfully copied the structure.
+  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+  @retval EFI_INVALID_PARAMETER Structure type was unknown.
+  @retval EFI_INVALID_PARAMETER Structure length was wrong for its type.
+  @retval EFI_UNSUPPORTED       Header passed in is not supported.
+**/
+EFI_STATUS
+CopyStructure (
+  IN  EFI_ACPI_DESCRIPTION_HEADER *Header,
+  IN  STRUCTURE_HEADER *Structure,
+  OUT STRUCTURE_HEADER **NewStructure
+  )
+{
+  STRUCTURE_HEADER      *NewStructureInternal;
+  STRUCTURE_HEADER      *StructureTable;
+  UINTN                 TableNumEntries;
+  BOOLEAN               EntryFound;
+  UINT8                 Index;
+
+  //
+  // Initialize the number of table entries and the table based on the table header passed in.
+  //
+  if (Header->Signature == EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+    TableNumEntries = sizeof (mMadtStructureTable) / sizeof (STRUCTURE_HEADER);
+    StructureTable = mMadtStructureTable;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check the incoming structure against the table of supported structures.
+  //
+  EntryFound = FALSE;
+  for (Index = 0; Index < TableNumEntries; Index++) {
+    if (Structure->Type == StructureTable[Index].Type) {
+      if (Structure->Length == StructureTable[Index].Length) {
+        EntryFound = TRUE;
+      } else {
+        DEBUG ((
+          DEBUG_ERROR,
+          "Invalid length for structure type %d: expected %d, actually %d\n",
+          Structure->Type,
+          StructureTable[Index].Length,
+          Structure->Length
+          ));
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+  }
+
+  //
+  // If no entry in the table matches the structure type and length passed in
+  // then return invalid parameter.
+  //
+  if (!EntryFound) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "Unknown structure type: %d\n",
+      Structure->Type
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NewStructureInternal = (STRUCTURE_HEADER *) AllocatePool (Structure->Length);
+  if (NewStructureInternal == NULL) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "Failed to allocate %d bytes for type %d structure\n",
+      Structure->Length,
+      Structure->Type
+      ));
+    return EFI_OUT_OF_RESOURCES;
+  } else {
+    DEBUG ((
+      DEBUG_INFO,
+      "Successfully allocated %d bytes for type %d structure at 0x%p\n",
+      Structure->Length,
+      Structure->Type,
+      NewStructureInternal
+      ));
+  }
+
+  CopyMem (
+    (VOID *) NewStructureInternal,
+    (VOID *) Structure,
+    Structure->Length
+    );
+
+  *NewStructure = NewStructureInternal;
+  return EFI_SUCCESS;
+}
+
+/**
+  Build ACPI Table. MADT tables supported.
+
+  This function builds the ACPI table from the header plus the list of sub-structures
+  passed in. The table returned by this function is ready to be installed using
+  the ACPI table protocol's InstallAcpiTable function, which copies it into
+  ACPI memory. After that, the caller should free the memory returned by this
+  function.
+
+  @param[in]  AcpiHeader             Pointer to the header structure.
+  @param[in]  TableSpecificHdrLength Size of the table specific header, not the ACPI standard header size.
+  @param[in]  Structures             Pointer to an array of sub-structure pointers.
+  @param[in]  StructureCount         Number of structure pointers in the array.
+  @param[out] NewTable               Newly allocated and initialized pointer to the ACPI Table.
+
+  @retval EFI_SUCCESS           Successfully built the ACPI table.
+  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+  @retval EFI_INVALID_PARAMETER Header parameter had the wrong signature.
+  @retval EFI_OUT_OF_RESOURCES  Space for the ACPI Table could not be allocated.
+**/
+EFI_STATUS
+BuildAcpiTable (
+  IN  EFI_ACPI_DESCRIPTION_HEADER  *AcpiHeader,
+  IN  UINTN                        TableSpecificHdrLength,
+  IN  STRUCTURE_HEADER             **Structures,
+  IN  UINTN                        StructureCount,
+  OUT UINT8                        **NewTable
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
+  UINTN                       Index;
+  UINT8                       *CurrPtr;
+  UINT8                       *EndOfTablePtr;
+
+  if (AcpiHeader == NULL) {
+    DEBUG ((DEBUG_ERROR, "AcpiHeader pointer is NULL\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (AcpiHeader->Signature != EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "MADT header signature is expected, actually 0x%08x\n",
+      AcpiHeader->Signature
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Structures == NULL) {
+    DEBUG ((DEBUG_ERROR, "Structure array pointer is NULL\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (Index = 0; Index < StructureCount; Index++) {
+    if (Structures[Index] == NULL) {
+      DEBUG ((DEBUG_ERROR, "Structure pointer %d is NULL\n", Index));
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Allocate the memory needed for the table.
+  //
+  Status = AllocateTable (
+    TableSpecificHdrLength,
+    Structures,
+    StructureCount,
+    &InternalTable
+    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Copy Header and patch in structure length, checksum is programmed later
+  // after all structures are populated.
+  //
+  CopyMem (
+    (VOID *) InternalTable,
+    (VOID *) AcpiHeader,
+    TableSpecificHdrLength
+    );
+
+  InternalTable->Length = GetTableSize (TableSpecificHdrLength, Structures, StructureCount);
+
+  //
+  // Copy all the sub structures to the table.
+  //
+  CurrPtr = ((UINT8 *) InternalTable) + TableSpecificHdrLength;
+  EndOfTablePtr = ((UINT8 *) InternalTable) + InternalTable->Length;
+
+  for (Index = 0; Index < StructureCount; Index++) {
+    ASSERT (Structures[Index] != NULL);
+    if (Structures[Index] == NULL) {
+      break;
+    }
+
+    CopyMem (
+      (VOID *) CurrPtr,
+      (VOID *) Structures[Index],
+      Structures[Index]->Length
+      );
+
+    CurrPtr += Structures[Index]->Length;
+    ASSERT (CurrPtr <= EndOfTablePtr);
+    if (CurrPtr > EndOfTablePtr) {
+      break;
+    }
+  }
+
+  //
+  // Update the return pointer.
+  //
+  *NewTable = (UINT8 *) InternalTable;
+  return EFI_SUCCESS;
+}
+
+/**
+  Build from scratch and install the MADT.
+
+  @retval EFI_SUCCESS           The MADT was installed successfully.
+  @retval EFI_OUT_OF_RESOURCES  Could not allocate required structures.
+**/
+EFI_STATUS
+InstallMadtFromScratch (
+  VOID
+  )
+{
+  EFI_STATUS                                          Status;
+  UINTN                                               Index;
+  EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *NewMadtTable;
+  UINTN                                               TableHandle;
+  EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MadtTableHeader;
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE         ProcLocalApicStruct;
+  EFI_ACPI_4_0_IO_APIC_STRUCTURE                      IoApicStruct;
+  EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE    IntSrcOverrideStruct;
+  EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE               LocalApciNmiStruct;
+  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE       ProcLocalX2ApicStruct;
+  EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE             LocalX2ApicNmiStruct;
+  STRUCTURE_HEADER                                    **MadtStructs;
+  UINTN                                               MaxMadtStructCount;
+  UINTN                                               MadtStructsIndex;
+  UINT32                                              CurrentIoApicAddress = (UINT32)(PcdGet32(PcdPcIoApicAddressBase));
+  UINT32                                              PcIoApicEnable;
+  UINT32                                              PcIoApicMask;
+  UINTN                                               PcIoApicIndex;
+
+  DetectApicIdMap();
+
+  // Call for Local APIC ID Reorder
+  SortCpuLocalApicInTable ();
+
+  NewMadtTable = NULL;
+
+  MaxMadtStructCount = (UINT32) (
+    MAX_CPU_NUM +    // processor local APIC structures
+    MAX_CPU_NUM +    // processor local x2APIC structures
+    1 + PcdGet8(PcdPcIoApicCount) +   // I/O APIC structures
+    2 +              // interrupt source override structures
+    1 +              // local APIC NMI structures
+    1                // local x2APIC NMI structures
+    );               // other structures are not used
+
+  MadtStructs = (STRUCTURE_HEADER **) AllocateZeroPool (MaxMadtStructCount * sizeof (STRUCTURE_HEADER *));
+  if (MadtStructs == NULL) {
+    DEBUG ((DEBUG_ERROR, "Could not allocate MADT structure pointer array\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the next index into the structure pointer array. It is
+  // incremented every time a structure of any type is copied to the array.
+  //
+  MadtStructsIndex = 0;
+
+  //
+  // Initialize MADT Header Structure
+  //
+  Status = InitializeMadtHeader (&MadtTableHeader);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "InitializeMadtHeader failed: %r\n", Status));
+    goto Done;
+  }
+
+  DEBUG ((EFI_D_INFO, "Number of CPUs detected = %d \n", mNumberOfCPUs));
+
+  //
+  // Build Processor Local APIC Structures and Processor Local X2APIC Structures
+  //
+  ProcLocalApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC;
+  ProcLocalApicStruct.Length = sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
+
+  ProcLocalX2ApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC;
+  ProcLocalX2ApicStruct.Length = sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE);
+  ProcLocalX2ApicStruct.Reserved[0] = 0;
+  ProcLocalX2ApicStruct.Reserved[1] = 0;
+
+  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+    //
+    // If x2APIC mode is not enabled, and if it is possible to express the
+    // APIC ID as a UINT8, use a processor local APIC structure. Otherwise,
+    // use a processor local x2APIC structure.
+    //
+    if (!mX2ApicEnabled && mCpuApicIdOrderTable[Index].ApicId < MAX_UINT8) {
+      ProcLocalApicStruct.Flags           = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+      ProcLocalApicStruct.ApicId          = (UINT8) mCpuApicIdOrderTable[Index].ApicId;
+      ProcLocalApicStruct.AcpiProcessorId = (UINT8) mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+      ASSERT (MadtStructsIndex < MaxMadtStructCount);
+      Status = CopyStructure (
+        &MadtTableHeader.Header,
+        (STRUCTURE_HEADER *) &ProcLocalApicStruct,
+        &MadtStructs[MadtStructsIndex++]
+        );
+    } else if (mCpuApicIdOrderTable[Index].ApicId != 0xFFFFFFFF) {
+      ProcLocalX2ApicStruct.Flags            = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+      ProcLocalX2ApicStruct.X2ApicId         = mCpuApicIdOrderTable[Index].ApicId;
+      ProcLocalX2ApicStruct.AcpiProcessorUid = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+      ASSERT (MadtStructsIndex < MaxMadtStructCount);
+      Status = CopyStructure (
+        &MadtTableHeader.Header,
+        (STRUCTURE_HEADER *) &ProcLocalX2ApicStruct,
+        &MadtStructs[MadtStructsIndex++]
+        );
+    }
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "CopyMadtStructure (local APIC/x2APIC) failed: %r\n", Status));
+      goto Done;
+    }
+  }
+
+  //
+  // Build I/O APIC Structures
+  //
+  IoApicStruct.Type = EFI_ACPI_4_0_IO_APIC;
+  IoApicStruct.Length = sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE);
+  IoApicStruct.Reserved = 0;
+
+  PcIoApicEnable = PcdGet32(PcdPcIoApicEnable);
+
+  if (FixedPcdGet32(PcdMaxCpuSocketCount) <= 4) {
+    IoApicStruct.IoApicId                  = PcdGet8(PcdIoApicId);
+    IoApicStruct.IoApicAddress             = PcdGet32(PcdIoApicAddress);
+    IoApicStruct.GlobalSystemInterruptBase = 0;
+    ASSERT (MadtStructsIndex < MaxMadtStructCount);
+    Status = CopyStructure (
+      &MadtTableHeader.Header,
+      (STRUCTURE_HEADER *) &IoApicStruct,
+      &MadtStructs[MadtStructsIndex++]
+      );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n", Status));
+      goto Done;
+    }
+  }
+
+  for (PcIoApicIndex = 0; PcIoApicIndex < PcdGet8(PcdPcIoApicCount); PcIoApicIndex++) {
+      PcIoApicMask = (1 << PcIoApicIndex);
+      if ((PcIoApicEnable & PcIoApicMask) == 0) {
+        continue;
+      }
+
+      IoApicStruct.IoApicId                  = (UINT8)(PcdGet8(PcdPcIoApicIdBase) + PcIoApicIndex);
+      IoApicStruct.IoApicAddress             = CurrentIoApicAddress;
+      CurrentIoApicAddress                   = (CurrentIoApicAddress & 0xFFFF8000) + 0x8000;
+      IoApicStruct.GlobalSystemInterruptBase = (UINT32)(24 + (PcIoApicIndex * 8));
+      ASSERT (MadtStructsIndex < MaxMadtStructCount);
+      Status = CopyStructure (
+        &MadtTableHeader.Header,
+        (STRUCTURE_HEADER *) &IoApicStruct,
+        &MadtStructs[MadtStructsIndex++]
+        );
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n", Status));
+        goto Done;
+      }
+  }
+
+  //
+  // Build Interrupt Source Override Structures
+  //
+  IntSrcOverrideStruct.Type = EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE;
+  IntSrcOverrideStruct.Length = sizeof (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+
+  //
+  // IRQ0=>IRQ2 Interrupt Source Override Structure
+  //
+  IntSrcOverrideStruct.Bus = 0x0;                   // Bus - ISA
+  IntSrcOverrideStruct.Source = 0x0;                // Source - IRQ0
+  IntSrcOverrideStruct.GlobalSystemInterrupt = 0x2; // Global System Interrupt - IRQ2
+  IntSrcOverrideStruct.Flags = 0x0;                 // Flags - Conforms to specifications of the bus
+
+  ASSERT (MadtStructsIndex < MaxMadtStructCount);
+  Status = CopyStructure (
+    &MadtTableHeader.Header,
+    (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+    &MadtStructs[MadtStructsIndex++]
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ2 source override) failed: %r\n", Status));
+    goto Done;
+  }
+
+  //
+  // IRQ9 (SCI Active High) Interrupt Source Override Structure
+  //
+  IntSrcOverrideStruct.Bus = 0x0;                   // Bus - ISA
+  IntSrcOverrideStruct.Source = 0x9;                // Source - IRQ9
+  IntSrcOverrideStruct.GlobalSystemInterrupt = 0x9; // Global System Interrupt - IRQ9
+  IntSrcOverrideStruct.Flags = 0xD;                 // Flags - Level-tiggered, Active High
+
+  ASSERT (MadtStructsIndex < MaxMadtStructCount);
+  Status = CopyStructure (
+    &MadtTableHeader.Header,
+    (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+    &MadtStructs[MadtStructsIndex++]
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ9 source override) failed: %r\n", Status));
+    goto Done;
+  }
+
+  //
+  // Build Local APIC NMI Structures
+  //
+  LocalApciNmiStruct.Type   = EFI_ACPI_4_0_LOCAL_APIC_NMI;
+  LocalApciNmiStruct.Length = sizeof (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE);
+  LocalApciNmiStruct.AcpiProcessorId = 0xFF;      // Applies to all processors
+  LocalApciNmiStruct.Flags           = 0x000D;    // Flags - Level-tiggered, Active High
+  LocalApciNmiStruct.LocalApicLint   = 0x1;
+
+  ASSERT (MadtStructsIndex < MaxMadtStructCount);
+  Status = CopyStructure (
+    &MadtTableHeader.Header,
+    (STRUCTURE_HEADER *) &LocalApciNmiStruct,
+    &MadtStructs[MadtStructsIndex++]
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (APIC NMI) failed: %r\n", Status));
+    goto Done;
+  }
+
+  //
+  // Build Local x2APIC NMI Structure
+  //
+  LocalX2ApicNmiStruct.Type   = EFI_ACPI_4_0_LOCAL_X2APIC_NMI;
+  LocalX2ApicNmiStruct.Length = sizeof (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE);
+  LocalX2ApicNmiStruct.Flags  = 0x000D;                // Flags - Level-tiggered, Active High
+  LocalX2ApicNmiStruct.AcpiProcessorUid = 0xFFFFFFFF;  // Applies to all processors
+  LocalX2ApicNmiStruct.LocalX2ApicLint  = 0x01;
+  LocalX2ApicNmiStruct.Reserved[0] = 0x00;
+  LocalX2ApicNmiStruct.Reserved[1] = 0x00;
+  LocalX2ApicNmiStruct.Reserved[2] = 0x00;
+
+  ASSERT (MadtStructsIndex < MaxMadtStructCount);
+  Status = CopyStructure (
+    &MadtTableHeader.Header,
+    (STRUCTURE_HEADER *) &LocalX2ApicNmiStruct,
+    &MadtStructs[MadtStructsIndex++]
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (x2APIC NMI) failed: %r\n", Status));
+    goto Done;
+  }
+
+  //
+  // Build Madt Structure from the Madt Header and collection of pointers in MadtStructs[]
+  //
+  Status = BuildAcpiTable (
+    (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
+    sizeof (EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER),
+    MadtStructs,
+    MadtStructsIndex,
+    (UINT8 **)&NewMadtTable
+    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "BuildAcpiTable failed: %r\n", Status));
+    goto Done;
+  }
+
+  //
+  // Publish Madt Structure to ACPI
+  //
+  Status = mAcpiTable->InstallAcpiTable (
+    mAcpiTable,
+    NewMadtTable,
+    NewMadtTable->Header.Length,
+    &TableHandle
+    );
+
+Done:
+  //
+  // Free memory
+  //
+  for (MadtStructsIndex = 0; MadtStructsIndex < MaxMadtStructCount; MadtStructsIndex++) {
+    if (MadtStructs[MadtStructsIndex] != NULL) {
+      FreePool (MadtStructs[MadtStructsIndex]);
+    }
+  }
+
+  FreePool (MadtStructs);
+
+  if (NewMadtTable != NULL) {
+    FreePool (NewMadtTable);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+InstallMcfgFromScratch (
+  VOID
+  )
+{
+  EFI_STATUS                                                                            Status;
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER                        *McfgTable;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *Segment;
+  UINTN                                                                                 Index;
+  UINTN                                                                                 SegmentCount;
+  PCI_SEGMENT_INFO                                                                      *PciSegmentInfo;
+  UINTN                                                                                 TableHandle;
+
+  PciSegmentInfo = GetPciSegmentInfo (&SegmentCount);
+
+  McfgTable = AllocateZeroPool (
+                sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) +
+                sizeof(EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE) * SegmentCount
+                );
+  if (McfgTable == NULL) {
+    DEBUG ((DEBUG_ERROR, "Could not allocate MCFG structure\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = InitializeHeader (
+    &McfgTable->Header,
+    EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+    0
+    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Set MCFG table "Length" field based on the number of PCIe segments enumerated so far
+  //
+  McfgTable->Header.Length = (UINT32)(sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) + 
+                                      sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE) * SegmentCount);
+
+  Segment = (VOID *)(McfgTable + 1);
+
+  for (Index = 0; Index < SegmentCount; Index++) {
+    Segment[Index].PciSegmentGroupNumber  = PciSegmentInfo[Index].SegmentNumber;
+    Segment[Index].BaseAddress    = PciSegmentInfo[Index].BaseAddress;
+    Segment[Index].StartBusNumber = PciSegmentInfo[Index].StartBusNumber;
+    Segment[Index].EndBusNumber   = PciSegmentInfo[Index].EndBusNumber;
+  }
+
+  //
+  // Publish Madt Structure to ACPI
+  //
+  Status = mAcpiTable->InstallAcpiTable (
+    mAcpiTable,
+    McfgTable,
+    McfgTable->Header.Length,
+    &TableHandle
+    );
+
+  return Status;
+}
+
+/**
+  This function will update any runtime platform specific information.
+  This currently includes:
+    Setting OEM table values, ID, table ID, creator ID and creator revision.
+    Enabling the proper processor entries in the APIC tables
+  It also indicates with which ACPI table version the table belongs.
+
+  @param[in] Table        The table to update
+  @param[in] Version      Where to install this table
+
+  @retval EFI_SUCCESS     Updated tables commplete.
+**/
+EFI_STATUS
+PlatformUpdateTables (
+  IN OUT EFI_ACPI_COMMON_HEADER       *Table,
+  IN OUT EFI_ACPI_TABLE_VERSION       *Version
+  )
+{
+  EFI_ACPI_DESCRIPTION_HEADER               *TableHeader;
+  UINT8                                     *TempOemId;
+  UINT64                                    TempOemTableId;
+  EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable;
+  UINT32                                           HpetBaseAddress;
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID     HpetBlockId;
+  UINT32                                           HpetCapabilitiesData;
+  HPET_GENERAL_CAPABILITIES_ID_REGISTER            HpetCapabilities;
+
+  TableHeader             = NULL;
+
+  //
+  // By default, a table belongs in all ACPI table versions published.
+  // Some tables will override this because they have different versions of the table.
+  //
+  TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+
+  //
+  // Update the OEM and creator information for every table except FACS.
+  //
+  if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
+    TempOemId = (UINT8 *)PcdGetPtr(PcdAcpiDefaultOemId);
+    CopyMem (&TableHeader->OemId, TempOemId, 6);
+
+    //
+    // Skip OEM table ID and creator information for DSDT, SSDT and PSDT tables, since these are
+    // created by an ASL compiler and the creator information is useful.
+    //
+    if (Table->Signature != EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
+        Table->Signature != EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
+        Table->Signature != EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
+        ) {
+      TempOemTableId = PcdGet64(PcdAcpiDefaultOemTableId);
+      CopyMem (&TableHeader->OemTableId, &TempOemTableId, 8);
+
+      //
+      // Update the creator ID
+      //
+      TableHeader->CreatorId = PcdGet32(PcdAcpiDefaultCreatorId);
+
+      //
+      // Update the creator revision
+      //
+      TableHeader->CreatorRevision = PcdGet32(PcdAcpiDefaultCreatorRevision);
+    }
+  }
+
+
+  //
+  // By default, a table belongs in all ACPI table versions published.
+  // Some tables will override this because they have different versions of the table.
+  //
+  *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+  //
+  // Update the various table types with the necessary updates
+  //
+  switch (Table->Signature) {
+
+  case EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+    ASSERT(FALSE);
+    break;
+
+  case EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+    FadtHeader    = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
+
+    FadtHeader->PreferredPmProfile = PcdGet8 (PcdFadtPreferredPmProfile);
+    FadtHeader->IaPcBootArch       = PcdGet16 (PcdFadtIaPcBootArch);
+    FadtHeader->Flags              = PcdGet32 (PcdFadtFlags);
+
+    FadtHeader->AcpiEnable  = PcdGet8 (PcdAcpiEnableSwSmi);
+    FadtHeader->AcpiDisable = PcdGet8 (PcdAcpiDisableSwSmi);
+
+    FadtHeader->Pm1aEvtBlk = PcdGet16 (PcdAcpiPm1AEventBlockAddress);
+    FadtHeader->Pm1bEvtBlk = PcdGet16 (PcdAcpiPm1BEventBlockAddress);
+    FadtHeader->Pm1aCntBlk = PcdGet16 (PcdAcpiPm1AControlBlockAddress);
+    FadtHeader->Pm1bCntBlk = PcdGet16 (PcdAcpiPm1BControlBlockAddress);
+    FadtHeader->Pm2CntBlk  = PcdGet16 (PcdAcpiPm2ControlBlockAddress);
+    FadtHeader->PmTmrBlk   = PcdGet16 (PcdAcpiPmTimerBlockAddress);
+    FadtHeader->Gpe0Blk    = PcdGet16 (PcdAcpiGpe0BlockAddress);
+    FadtHeader->Gpe1Blk    = PcdGet16 (PcdAcpiGpe1BlockAddress);
+
+    FadtHeader->XPm1aEvtBlk.Address = PcdGet16 (PcdAcpiPm1AEventBlockAddress);
+    FadtHeader->XPm1bEvtBlk.Address = PcdGet16 (PcdAcpiPm1BEventBlockAddress);
+    if (FadtHeader->XPm1bEvtBlk.Address == 0) {
+      FadtHeader->XPm1bEvtBlk.AccessSize = 0;
+    }
+    FadtHeader->XPm1aCntBlk.Address = PcdGet16 (PcdAcpiPm1AControlBlockAddress);
+    FadtHeader->XPm1bCntBlk.Address = PcdGet16 (PcdAcpiPm1BControlBlockAddress);
+    if (FadtHeader->XPm1bCntBlk.Address == 0) {
+      FadtHeader->XPm1bCntBlk.AccessSize = 0;
+    }
+    FadtHeader->XPm2CntBlk.Address  = PcdGet16 (PcdAcpiPm2ControlBlockAddress);
+    //if (FadtHeader->XPm2CntBlk.Address == 0) {
+      FadtHeader->XPm2CntBlk.AccessSize = 0;
+    //}
+    FadtHeader->XPmTmrBlk.Address   = PcdGet16 (PcdAcpiPmTimerBlockAddress);
+    FadtHeader->XGpe0Blk.Address    = PcdGet16 (PcdAcpiGpe0BlockAddress);
+    FadtHeader->XGpe1Blk.Address    = PcdGet16 (PcdAcpiGpe1BlockAddress);
+    if (FadtHeader->XGpe1Blk.Address == 0) {
+      FadtHeader->XGpe1Blk.AccessSize = 0;
+    }
+
+    DEBUG(( EFI_D_ERROR, "ACPI FADT table @ address 0x%x\n", Table ));
+    DEBUG(( EFI_D_ERROR, "  IaPcBootArch 0x%x\n", FadtHeader->IaPcBootArch ));
+    DEBUG(( EFI_D_ERROR, "  Flags 0x%x\n", FadtHeader->Flags ));
+    break;
+
+  case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+    HpetTable = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *)Table;
+    HpetBaseAddress = PcdGet32 (PcdHpetBaseAddress);
+    HpetTable->BaseAddressLower32Bit.Address = HpetBaseAddress;
+    HpetTable->BaseAddressLower32Bit.RegisterBitWidth = 0;
+    HpetCapabilitiesData     = MmioRead32 (HpetBaseAddress + HPET_GENERAL_CAPABILITIES_ID_OFFSET);
+    HpetCapabilities.Uint64  = HpetCapabilitiesData;
+    HpetCapabilitiesData     = MmioRead32 (HpetBaseAddress + HPET_GENERAL_CAPABILITIES_ID_OFFSET + 4);
+    HpetCapabilities.Uint64 |= LShiftU64 (HpetCapabilitiesData, 32);
+    HpetBlockId.Bits.Revision       = HpetCapabilities.Bits.Revision;
+    HpetBlockId.Bits.NumberOfTimers = HpetCapabilities.Bits.NumberOfTimers;
+    HpetBlockId.Bits.CounterSize    = HpetCapabilities.Bits.CounterSize;
+    HpetBlockId.Bits.Reserved       = 0;
+    HpetBlockId.Bits.LegacyRoute    = HpetCapabilities.Bits.LegacyRoute;
+    HpetBlockId.Bits.VendorId       = HpetCapabilities.Bits.VendorId;
+    HpetTable->EventTimerBlockId    = HpetBlockId.Uint32;
+    HpetTable->MainCounterMinimumClockTickInPeriodicMode = (UINT16)HpetCapabilities.Bits.CounterClockPeriod;
+    DEBUG(( EFI_D_ERROR, "ACPI HPET table @ address 0x%x\n", Table ));
+    DEBUG(( EFI_D_ERROR, "  HPET base 0x%x\n", PcdGet32 (PcdHpetBaseAddress) ));
+    break;
+
+  case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+    ASSERT(FALSE);
+    break;
+
+  default:
+    break;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  This function calculates RCR based on PCI Device ID and Vendor ID from the devices
+  available on the platform.
+  It also includes other instances of BIOS change to calculate CRC and provides as
+  HWSignature filed in FADT table.
+**/
+VOID
+IsHardwareChange (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         Index;
+  UINTN                         HandleCount;
+  EFI_HANDLE                    *HandleBuffer;
+  EFI_PCI_IO_PROTOCOL           *PciIo;
+  UINT32                        CRC;
+  UINT32                        *HWChange;
+  UINTN                         HWChangeSize;
+  UINT32                        PciId;
+  UINTN                         Handle;
+  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr;
+  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE    *pFADT;
+
+  HandleCount  = 0;
+  HandleBuffer = NULL;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiPciIoProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return; // PciIO protocol not installed yet!
+  }
+
+  //
+  // Allocate memory for HWChange and add additional entrie for
+  // pFADT->XDsdt
+  //
+  HWChangeSize = HandleCount + 1;
+  HWChange = AllocateZeroPool( sizeof(UINT32) * HWChangeSize );
+  ASSERT( HWChange != NULL );
+
+  if (HWChange == NULL) return;
+
+  //
+  // add HWChange inputs: PCI devices
+  //
+  for (Index = 0; HandleCount > 0; HandleCount--) {
+    PciId = 0;
+    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
+    if (!EFI_ERROR (Status)) {
+      Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &PciId);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+      HWChange[Index++] = PciId;
+    }
+  }
+
+  //
+  // Locate FACP Table
+  //
+  Handle = 0;
+  Status = LocateAcpiTableBySignature (
+              EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+              (EFI_ACPI_DESCRIPTION_HEADER **) &pFADT,
+              &Handle
+              );
+  if (EFI_ERROR (Status) || (pFADT == NULL)) {
+    return;  //Table not found or out of memory resource for pFADT table
+  }
+
+  //
+  // add HWChange inputs: others
+  //
+  HWChange[Index++] = (UINT32)pFADT->XDsdt;
+
+  //
+  // Calculate CRC value with HWChange data.
+  //
+  Status = gBS->CalculateCrc32(HWChange, HWChangeSize, &CRC);
+  DEBUG((DEBUG_INFO, "CRC = %x and Status = %r\n", CRC, Status));
+
+  //
+  // Set HardwareSignature value based on CRC value.
+  //
+  FacsPtr = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)pFADT->FirmwareCtrl;
+  FacsPtr->HardwareSignature = CRC;
+  FreePool( HWChange );
+}
+
+VOID
+UpdateLocalTable (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_ACPI_COMMON_HEADER        *CurrentTable;
+  EFI_ACPI_TABLE_VERSION        Version;
+  UINTN                         TableHandle;
+  UINTN                         Index;
+
+  for (Index = 0; Index < sizeof(mLocalTable)/sizeof(mLocalTable[0]); Index++) {
+    CurrentTable = mLocalTable[Index];
+
+    PlatformUpdateTables (CurrentTable, &Version);
+
+    TableHandle = 0;
+
+    if (Version != EFI_ACPI_TABLE_VERSION_NONE) {
+      Status = mAcpiTable->InstallAcpiTable (
+                              mAcpiTable,
+                              CurrentTable,
+                              CurrentTable->Length,
+                              &TableHandle
+                              );
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+}
+
+
+VOID
+EFIAPI
+AcpiEndOfDxeEvent (
+  EFI_EVENT           Event,
+  VOID                *ParentImageHandle
+  )
+{
+
+  if (Event != NULL) {
+    gBS->CloseEvent(Event);
+  }
+
+
+  //
+  // Calculate Hardware Signature value based on current platform configurations
+  //
+  IsHardwareChange();
+}
+
+/**
+  ACPI Platform driver installation function.
+
+  @param[in] ImageHandle     Handle for this drivers loaded image protocol.
+  @param[in] SystemTable     EFI system table.
+
+  @retval EFI_SUCCESS        The driver installed without error.
+  @retval EFI_ABORTED        The driver encountered an error and could not complete installation of
+                             the ACPI tables.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiPlatform (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_EVENT                     EndOfDxeEvent;
+
+
+  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&mAcpiTable);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Create an End of DXE event.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  AcpiEndOfDxeEvent,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Determine the number of processors
+  //
+  mMpService->GetNumberOfProcessors (
+              mMpService,
+              &mNumberOfCPUs,
+              &mNumberOfEnabledCPUs
+              );
+  ASSERT (mNumberOfCPUs <= MAX_CPU_NUM && mNumberOfEnabledCPUs >= 1);
+  DEBUG ((DEBUG_INFO, "mNumberOfCPUs - %d\n", mNumberOfCPUs));
+  DEBUG ((DEBUG_INFO, "mNumberOfEnabledCPUs - %d\n", mNumberOfEnabledCPUs));
+
+  DEBUG ((DEBUG_INFO, "mX2ApicEnabled - 0x%x\n", mX2ApicEnabled));
+  DEBUG ((DEBUG_INFO, "mForceX2ApicId - 0x%x\n", mForceX2ApicId));
+
+  // support up to 64 threads/socket
+  AsmCpuidEx(CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL, NULL, NULL);
+  mNumOfBitShift &= 0x1F;
+  DEBUG ((DEBUG_INFO, "mNumOfBitShift - 0x%x\n", mNumOfBitShift));
+
+  UpdateLocalTable ();
+
+  InstallMadtFromScratch ();
+  InstallMcfgFromScratch ();
+
+  return EFI_SUCCESS;
+}

+ 45 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h

@@ -0,0 +1,45 @@
+/** @file
+  This is an implementation of the ACPI platform driver.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+//
+// Statements that include other header files
+//
+
+#include <Base.h>
+#include <Uefi.h>
+#include <IndustryStandard/Pci30.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
+#include <Register/Hpet.h>
+#include <Guid/EventGroup.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BoardAcpiTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/AslUpdateLib.h>
+#include <Library/PciSegmentInfoLib.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/MpService.h>
+#include <Protocol/PciIo.h>
+
+#include <Register/Cpuid.h>
+
+#endif

+ 105 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf

@@ -0,0 +1,105 @@
+## @file
+#  Component information file for AcpiPlatform module
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiPlatform
+  FILE_GUID                      = FC90EB7A-3E0A-483C-A26C-484D36593FF4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InstallAcpiPlatform
+
+[Sources.common]
+  AcpiPlatform.h
+  AcpiPlatform.c
+  Fadt/Fadt.c
+  Facs/Facs.c
+  Hpet/Hpet.c
+  Wsmt/Wsmt.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  BaseLib
+  DebugLib
+  IoLib
+  PcdLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  HobLib
+  PciSegmentInfoLib
+  AslUpdateLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicEnable
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicCount
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicIdBase
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicAddressBase
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicInterruptBase
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuThreadCount
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtPreferredPmProfile
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtIaPcBootArch
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtFlags
+
+  gPcAtChipsetPkgTokenSpaceGuid.PcdHpetBaseAddress
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdPciExpressRegionLength
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiEnableSwSmi
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiDisableSwSmi
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AEventBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BEventBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AControlBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BControlBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm2ControlBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPmTimerBlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe0BlockAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe1BlockAddress
+
+  gMinPlatformPkgTokenSpaceGuid.PcdLocalApicAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdIoApicAddress
+  gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+  gMinPlatformPkgTokenSpaceGuid.PcdWsmtProtectionFlags
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     ## CONSUMES
+  gEfiMpServiceProtocolGuid                     ## CONSUMES
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+
+[Guids]
+  gEfiGlobalVariableGuid                        ## CONSUMES
+  gEfiHobListGuid                               ## CONSUMES
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
+
+[Depex]
+  gEfiAcpiTableProtocolGuid           AND
+  gEfiMpServiceProtocolGuid           AND
+  gEfiPciRootBridgeIoProtocolGuid     AND
+  gEfiVariableArchProtocolGuid        AND
+  gEfiVariableWriteArchProtocolGuid
+
+

+ 84 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c

@@ -0,0 +1,84 @@
+/** @file
+  This file contains a structure definition for the ACPI 5.0 Firmware ACPI
+  Control Structure (FACS).  The contents of this file should only be modified
+  for bug fixes, no porting is required.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+
+//
+// FACS Definitions
+//
+#define EFI_ACPI_FIRMWARE_WAKING_VECTOR 0x00000000
+#define EFI_ACPI_GLOBAL_LOCK            0x00000000
+
+//
+// Firmware Control Structure Feature Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS 0x00000000
+
+#define EFI_ACPI_X_FIRMWARE_WAKING_VECTOR         0x0000000000000000
+
+#define EFI_ACPI_OSPM_FLAGS                       0x00000000
+
+
+//
+// Firmware ACPI Control Structure
+// Please modify all values in Facs.h only.
+//
+
+EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs = {
+  EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+  sizeof (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+
+  //
+  // Hardware Signature will be updated at runtime
+  //
+  0x00000000,
+
+  EFI_ACPI_FIRMWARE_WAKING_VECTOR,
+  EFI_ACPI_GLOBAL_LOCK,
+  EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS,
+  EFI_ACPI_X_FIRMWARE_WAKING_VECTOR,
+  EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  },
+  EFI_ACPI_OSPM_FLAGS,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  }
+};

+ 359 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c

@@ -0,0 +1,359 @@
+/** @file
+  This file contains a structure definition for the ACPI 5.0 Fixed ACPI
+  Description Table (FADT).  The contents of this file should only be modified
+  for bug fixes, no porting is required.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// FADT Definitions
+//
+#define EFI_ACPI_OEM_FADT_REVISION    0x00000000
+
+#define EFI_ACPI_PREFERRED_PM_PROFILE 0x00 // To be fixed
+
+#define EFI_ACPI_SCI_INT              0x0009
+#define EFI_ACPI_SMI_CMD              0x000000B2
+
+#define EFI_ACPI_ACPI_ENABLE          0 // To be fixed
+#define EFI_ACPI_ACPI_DISABLE         0 // To be fixed
+#define EFI_ACPI_S4_BIOS_REQ          0x00
+#define EFI_ACPI_CST_CNT              0x00
+
+#define EFI_ACPI_PSTATE_CNT           0x00
+#define EFI_ACPI_GPE1_BASE            (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 2)
+#define EFI_ACPI_P_LVL2_LAT           0x0065 // 101
+#define EFI_ACPI_P_LVL3_LAT           0x03E9 // 1001
+#define EFI_ACPI_FLUSH_SIZE           0x0000
+#define EFI_ACPI_FLUSH_STRIDE         0x0000
+#define EFI_ACPI_DUTY_OFFSET          0x01
+#define EFI_ACPI_DUTY_WIDTH           0x00
+
+#define EFI_ACPI_DAY_ALRM             0x0D
+#define EFI_ACPI_MON_ALRM             0x00
+#define EFI_ACPI_CENTURY              0x32
+
+//
+// IA-PC Boot Architecture Flags
+//
+
+#define EFI_ACPI_IAPC_BOOT_ARCH       0 // To be fixed
+
+//
+// Fixed Feature Flags
+//
+#define EFI_ACPI_FIXED_FEATURE_FLAGS  0 // To be fixed
+
+//
+// PM1A Event Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH         0x20
+#define EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS           0 // To be fixed
+
+//
+// PM1B Event Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH         0x00
+#define EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS           0 // To be fixed
+
+//
+// PM1A Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH         0x10
+#define EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS           0 // To be fixed
+
+//
+// PM1B Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH         0x00
+#define EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS           0 // To be fixed
+
+//
+// PM2 Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH        0x08
+#define EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET       0x00
+#define EFI_ACPI_PM2_CNT_BLK_ADDRESS          0 // To be fixed
+
+//
+// Power Management Timer Control Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM_TMR_BLK_BIT_WIDTH         0x20
+#define EFI_ACPI_PM_TMR_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_PM_TMR_BLK_ADDRESS           0 // To be fixed
+
+//
+// General Purpose Event 0 Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE0_BLK_BIT_WIDTH         0  // size of R_PCH_ACPI_GPE0_STS_127_96 + R_PCH_ACPI_GPE0_EN_127_96
+#define EFI_ACPI_GPE0_BLK_BIT_OFFSET        0x00
+#define EFI_ACPI_GPE0_BLK_ADDRESS           0 // To be fixed
+
+//
+// General Purpose Event 1 Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE1_BLK_BIT_WIDTH         0x0
+#define EFI_ACPI_GPE1_BLK_BIT_OFFSET        0x0
+#define EFI_ACPI_GPE1_BLK_ADDRESS           0 // To be fixed
+//
+// Reset Register Generic Address Information
+//
+#define EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_RESET_REG_BIT_WIDTH        0x08
+#define EFI_ACPI_RESET_REG_BIT_OFFSET       0x00
+#define EFI_ACPI_RESET_REG_ADDRESS          0x00000CF9
+#define EFI_ACPI_RESET_VALUE                0x06
+
+//
+// Number of bytes decoded by PM1 event blocks (a and b)
+//
+#define EFI_ACPI_PM1_EVT_LEN  ((EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH + EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH) / 8)
+
+//
+// Number of bytes decoded by PM1 control blocks (a and b)
+//
+#define EFI_ACPI_PM1_CNT_LEN  ((EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH + EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH) / 8)
+
+//
+// Number of bytes decoded by PM2 control block
+//
+#define EFI_ACPI_PM2_CNT_LEN  (EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by PM timer block
+//
+#define EFI_ACPI_PM_TMR_LEN (EFI_ACPI_PM_TMR_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by GPE0 block
+//
+#define EFI_ACPI_GPE0_BLK_LEN (EFI_ACPI_GPE0_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by GPE1 block
+//
+#define EFI_ACPI_GPE1_BLK_LEN (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 8)
+
+//
+// Fixed ACPI Description Table
+// Please modify all values in Fadt.h only.
+//
+
+EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt = {
+  {
+    EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE),
+    EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+
+    //
+    // Checksum will be updated at runtime
+    //
+    0x00,
+
+    //
+    // It is expected that these values will be updated at runtime
+    //
+    { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+    0,
+    EFI_ACPI_OEM_FADT_REVISION,
+    0,
+    0
+  },
+
+  //
+  // These addresses will be updated at runtime
+  //
+  0x00000000,
+  0x00000000,
+
+  EFI_ACPI_RESERVED_BYTE,
+  EFI_ACPI_PREFERRED_PM_PROFILE,
+  EFI_ACPI_SCI_INT,
+  EFI_ACPI_SMI_CMD,
+  EFI_ACPI_ACPI_ENABLE,
+  EFI_ACPI_ACPI_DISABLE,
+  EFI_ACPI_S4_BIOS_REQ,
+  EFI_ACPI_PSTATE_CNT,
+
+  EFI_ACPI_PM1A_EVT_BLK_ADDRESS,
+  EFI_ACPI_PM1B_EVT_BLK_ADDRESS,
+  EFI_ACPI_PM1A_CNT_BLK_ADDRESS,
+  EFI_ACPI_PM1B_CNT_BLK_ADDRESS,
+  EFI_ACPI_PM2_CNT_BLK_ADDRESS,
+  EFI_ACPI_PM_TMR_BLK_ADDRESS,
+  EFI_ACPI_GPE0_BLK_ADDRESS,
+  EFI_ACPI_GPE1_BLK_ADDRESS,
+  EFI_ACPI_PM1_EVT_LEN,
+  EFI_ACPI_PM1_CNT_LEN,
+  EFI_ACPI_PM2_CNT_LEN,
+  EFI_ACPI_PM_TMR_LEN,
+  EFI_ACPI_GPE0_BLK_LEN,
+  EFI_ACPI_GPE1_BLK_LEN,
+  EFI_ACPI_GPE1_BASE,
+
+  //
+  // Latest OS have C-State capability and CST_CNT SMI doesn't need to be defined.
+  // CST_CNT SMI is not handled in BIOS and it can be removed safely.
+  //
+  EFI_ACPI_CST_CNT,
+  EFI_ACPI_P_LVL2_LAT,
+  EFI_ACPI_P_LVL3_LAT,
+  EFI_ACPI_FLUSH_SIZE,
+  EFI_ACPI_FLUSH_STRIDE,
+  EFI_ACPI_DUTY_OFFSET,
+  EFI_ACPI_DUTY_WIDTH,
+  EFI_ACPI_DAY_ALRM,
+  EFI_ACPI_MON_ALRM,
+  EFI_ACPI_CENTURY,
+  EFI_ACPI_IAPC_BOOT_ARCH,
+  EFI_ACPI_RESERVED_BYTE,
+  EFI_ACPI_FIXED_FEATURE_FLAGS,
+
+  //
+  // Reset Register Block
+  //
+  {
+    EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID,
+    EFI_ACPI_RESET_REG_BIT_WIDTH,
+    EFI_ACPI_RESET_REG_BIT_OFFSET,
+    EFI_ACPI_5_0_BYTE,
+    EFI_ACPI_RESET_REG_ADDRESS
+  },
+  EFI_ACPI_RESET_VALUE,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  },
+
+  //
+  // These addresses will be updated at runtime
+  //
+  0x0000000000000000, // X_FIRMWARE_CTRL
+  0x0000000000000000, // X_DSDT
+
+  {
+    //
+    // X_PM1a Event Register Block
+    //
+    EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH,
+    EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_WORD,
+    EFI_ACPI_PM1A_EVT_BLK_ADDRESS
+  },
+  {
+    //
+    // X_PM1b Event Register Block
+    //
+    EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH,
+    EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_WORD,
+    EFI_ACPI_PM1B_EVT_BLK_ADDRESS
+  },
+  {
+    //
+    // X_PM1a Control Register Block
+    //
+    EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH,
+    EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_WORD,
+    EFI_ACPI_PM1A_CNT_BLK_ADDRESS
+  },
+  {
+    //
+    // X_PM1b Control Register Block
+    //
+    EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH,
+    EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_WORD,
+    EFI_ACPI_PM1B_CNT_BLK_ADDRESS
+  },
+  {
+    //
+    // X_PM2 Control Register Block
+    //
+    EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH,
+    EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_BYTE,
+    EFI_ACPI_PM2_CNT_BLK_ADDRESS
+  },
+  {
+    //
+    // X_PM Timer Control Register Block
+    //
+    EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_PM_TMR_BLK_BIT_WIDTH,
+    EFI_ACPI_PM_TMR_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_DWORD,
+    EFI_ACPI_PM_TMR_BLK_ADDRESS
+  },
+  {
+    //
+    // X_General Purpose Event 0 Register Block
+    //
+    EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_GPE0_BLK_BIT_WIDTH,
+    EFI_ACPI_GPE0_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_BYTE,
+    EFI_ACPI_GPE0_BLK_ADDRESS
+  },
+  {
+    //
+    // X_General Purpose Event 1 Register Block
+    //
+    EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID,
+    EFI_ACPI_GPE1_BLK_BIT_WIDTH,
+    EFI_ACPI_GPE1_BLK_BIT_OFFSET,
+    EFI_ACPI_5_0_BYTE,
+    EFI_ACPI_GPE1_BLK_ADDRESS
+  },
+  {
+  //
+  // Sleep Control Reg - update in DXE driver
+  //
+    0,
+    0,
+    0,
+    0,
+    0
+  },
+  {
+  //
+  // Sleep Status Reg - update in DXE driver
+  //
+    0,
+    0,
+    0,
+    0,
+    0
+  }
+};

+ 78 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c

@@ -0,0 +1,78 @@
+/** @file
+  This file contains a structure definition for the ACPI 1.0 High Precision Event Timer
+  Description Table (HPET).  The contents of this file should only be modified
+  for bug fixes, no porting is required.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+
+//
+// HPET Definitions
+//
+#define EFI_ACPI_OEM_HPET_REVISION    0x00000001
+
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ID                   0x0 // To be filled
+
+//
+// Event Timer Block Base Address Information
+//
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID EFI_ACPI_3_0_SYSTEM_MEMORY
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH        0x40
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET       0x00
+#define EFI_ACPI_EVENT_TIMER_ACCESS_SIZE            0x00
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS          0x0 // To be filled
+
+#define EFI_ACPI_HPET_NUMBER                        0x00
+
+#define EFI_ACPI_MIN_CLOCK_TICK                     0x0080
+
+#define EFI_ACPI_HPET_ATTRIBUTES                    0x00
+
+//
+// High Precision Event Timer Table
+// Please modify all values in Hpet.h only.
+//
+
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet = {
+  {
+    EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER),
+    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
+
+    //
+    // Checksum will be updated at runtime
+    //
+    0x00,
+
+    //
+    // It is expected that these values will be updated at runtime
+    //
+    { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+    0,
+    EFI_ACPI_OEM_HPET_REVISION,
+    0,
+    0
+  },
+
+  EFI_ACPI_EVENT_TIMER_BLOCK_ID,
+  {
+    EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID,
+    EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH,
+    EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET,
+    EFI_ACPI_EVENT_TIMER_ACCESS_SIZE,
+    EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS
+  },
+  EFI_ACPI_HPET_NUMBER,
+  EFI_ACPI_MIN_CLOCK_TICK,
+  EFI_ACPI_HPET_ATTRIBUTES
+};

+ 46 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c

@@ -0,0 +1,46 @@
+/** @file
+  ACPI WSMT table
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
+#include <Library/PcdLib.h>
+
+//
+// WSMT Definitions
+//
+
+#define EFI_ACPI_OEM_WSMT_REVISION                      0x00000001
+
+EFI_ACPI_WSMT_TABLE Wsmt = {
+  {
+    EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_WSMT_TABLE),
+    EFI_WSMT_TABLE_REVISION,
+
+    //
+    // Checksum will be updated at runtime
+    //
+    0x00,
+
+    //
+    // It is expected that these values will be updated at runtime
+    //
+    { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+    0,
+    EFI_ACPI_OEM_WSMT_REVISION,
+    0,
+    0
+  },
+
+  FixedPcdGet32(PcdWsmtProtectionFlags)
+};

+ 75 - 0
Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h

@@ -0,0 +1,75 @@
+/** @file
+  Platform specific defines for constructing ACPI tables
+
+  Copyright (c) 2013 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID           'S','I','M','I','C','S'   // OEMID 6 bytes long
+#define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('S','I','M','I','C','S','T','B') // OEM table id 8 bytes long
+#define EFI_ACPI_OEM_REVISION     0x02000820
+#define EFI_ACPI_CREATOR_ID       SIGNATURE_32('Q','S','P',' ')
+#define EFI_ACPI_CREATOR_REVISION 0x00000097
+
+#define INT_MODEL       0x01
+#define SCI_INT_VECTOR  0x0009
+#define SMI_CMD_IO_PORT 0xB2
+#define ACPI_ENABLE     0x0E1
+#define ACPI_DISABLE    0x01E
+#define S4BIOS_REQ      0x00
+#define PM1a_EVT_BLK    0x00000400
+#define PM1b_EVT_BLK    0x00000000
+#define PM1a_CNT_BLK    0x00000404
+#define PM1b_CNT_BLK    0x00000000
+#define PM2_CNT_BLK     0x00000450
+#define PM_TMR_BLK      0x00000408
+#define GPE0_BLK        0x00000420
+#define GPE1_BLK        0x00000000
+#define PM1_EVT_LEN     0x04
+#define PM1_CNT_LEN     0x04
+#define PM2_CNT_LEN     0x01
+#define PM_TM_LEN       0x04
+#define GPE0_BLK_LEN    0x10
+#define GPE1_BLK_LEN    0x00
+#define GPE1_BASE       0x00
+#define RESERVED        0x00
+#define P_LVL2_LAT      0x0065
+#define P_LVL3_LAT      0x03E9
+#define FLUSH_SIZE      0x0400
+#define FLUSH_STRIDE    0x0010
+#define DUTY_OFFSET     0x00
+#define DUTY_WIDTH      0x00
+#define DAY_ALRM        0x0D
+#define MON_ALRM        0x00
+#define CENTURY         0x00
+#define FLAG            (EFI_ACPI_2_0_WBINVD | \
+                         EFI_ACPI_2_0_PROC_C1 | \
+                         EFI_ACPI_2_0_SLP_BUTTON | \
+                         EFI_ACPI_2_0_RTC_S4 | \
+                         EFI_ACPI_2_0_RESET_REG_SUP)
+#define RESET_REG       0xCF9
+#define RESET_VALUE     (BIT2 | BIT1) // PIIX3 Reset CPU + System Reset
+
+//
+// Byte-aligned IO port register block initializer for
+// EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE
+//
+#define GAS2_IO(Base, Size) {                             \
+          EFI_ACPI_2_0_SYSTEM_IO, /* AddressSpaceId    */ \
+          (Size) * 8,             /* RegisterBitWidth  */ \
+          0,                      /* RegisterBitOffset */ \
+          0,                      /* Reserved          */ \
+          (Base)                  /* Address           */ \
+          }
+
+#endif

BIN
Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp


+ 152 - 0
Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec

@@ -0,0 +1,152 @@
+## @file
+#  EFI/Framework Simics platform
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = SimicsOpenBoardPkg
+  PACKAGE_GUID                   = E6A03E0D-5944-4dc6-9292-090D609EDD3A
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[Guids]
+  gBoardModuleTokenSpaceGuid  = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+  gSimicsBoardConfigGuid  = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+
+[PcdsFixedAtBuild]
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase|0x0|UINT32|0
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize|0x0|UINT32|1
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase|0x0|UINT32|0x15
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize|0x0|UINT32|0x16
+
+  #TODO: Remove these two when we integrate new PlatformPei
+  gBoardModuleTokenSpaceGuid.PcdSimicsMemFvBase|0x00800000|UINT32|2
+  gBoardModuleTokenSpaceGuid.PcdSimicsMemFvSize|0x00500000|UINT32|3
+
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase|0x0|UINT32|0x8
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize|0x0|UINT32|0x9
+  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareFdSize|0x0|UINT32|0xa
+  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareBlockSize|0|UINT32|0xb
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase|0x0|UINT32|0xc
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase|0x0|UINT32|0xd
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe
+  gBoardModuleTokenSpaceGuid.PcdSimicsFdBaseAddress|0x0|UINT32|0xf
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase|0x0|UINT32|0x11
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesSize|0x0|UINT32|0x12
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|0x0|UINT32|0x13
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize|0x0|UINT32|0x14
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|0x0|UINT32|0x18
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize|0x0|UINT32|0x19
+  gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a
+  gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd|0x0|UINT32|0x1f
+
+[PcdsDynamic, PcdsDynamicEx]
+
+  # TODO: investigate whether next two Pcds are needed
+  gBoardModuleTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|0x28
+  gBoardModuleTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId|0|UINT16|0x1b
+
+  ## The IO port aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22
+  gBoardModuleTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23
+
+  ## The 32-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25
+
+  ## The 64-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27
+
+[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]
+  ## Pcd8259LegacyModeMask defines the default mask value for platform. This value is determined<BR><BR>
+  #  1) If platform only support pure UEFI, value should be set to 0xFFFF or 0xFFFE;
+  #     Because only clock interrupt is allowed in legacy mode in pure UEFI platform.<BR>
+  #  2) If platform install CSM and use thunk module:<BR>
+  #     a) If thunk call provided by CSM binary requires some legacy interrupt support, the corresponding bit
+  #        should be opened as 0.<BR>
+  #        For example, if keyboard interfaces provided CSM binary use legacy keyboard interrupt in 8259 bit 1, then
+  #        the value should be set to 0xFFFC.<BR>
+  #     b) If all thunk call provied by CSM binary do not require legacy interrupt support, value should be set
+  #        to 0xFFFF or 0xFFFE.<BR>
+  #
+  #  The default value of legacy mode mask could be changed by EFI_LEGACY_8259_PROTOCOL->SetMask(). But it is rarely
+  #  need change it except some special cases such as when initializing the CSM binary, it should be set to 0xFFFF to
+  #  mask all legacy interrupt. Please restore the original legacy mask value if changing is made for these special case.<BR>
+  # @Prompt 8259 Legacy Mode mask.
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF|UINT16|0x00000001
+
+  ## Pcd8259LegacyModeEdgeLevel defines the default edge level for legacy mode's interrrupt controller.
+  #  For the corresponding bits, 0 = Edge triggered and 1 = Level triggered.
+  # @Prompt 8259 Legacy Mode edge level.
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x00000002
+
+  ## Indicates if we need enable IsaAcpiCom1 device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiCom1 device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiCom1 device.<BR>
+  # @Prompt Enable IsaAcpiCom1 device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom1Enable|TRUE|BOOLEAN|0x00000003
+
+  ## Indicates if we need enable IsaAcpiCom2 device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiCom2 device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiCom2 device.<BR>
+  # @Prompt Enable IsaAcpiCom12 device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom2Enable|TRUE|BOOLEAN|0x00000004
+
+  ## Indicates if we need enable IsaAcpiPs2Keyboard device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiPs2Keyboard device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiPs2Keyboard device.<BR>
+  # @Prompt Enable IsaAcpiPs2Keyboard device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2KeyboardEnable|TRUE|BOOLEAN|0x00000005
+
+  ## Indicates if we need enable IsaAcpiPs2Mouse device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiPs2Mouse device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiPs2Mouse device.<BR>
+  # @Prompt Enable IsaAcpiPs2Mouse device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2MouseEnable|TRUE|BOOLEAN|0x00000006
+
+  ## Indicates if we need enable IsaAcpiFloppyA device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiFloppyA device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiFloppyA device.<BR>
+  # @Prompt Enable IsaAcpiFloppyA device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyAEnable|TRUE|BOOLEAN|0x00000007
+
+  ## Indicates if we need enable IsaAcpiFloppyB device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiFloppyB device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiFloppyB device.<BR>
+  # @Prompt Enable IsaAcpiFloppyB device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyBEnable|TRUE|BOOLEAN|0x00000008
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+  ## FFS filename to find the shell application.
+  # @Prompt FFS Name of Shell Application
+  gBoardModuleTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }|VOID*|0x40000004
+
+  ## ISA Bus features to support DMA, SlaveDMA and ISA Memory. <BR><BR>
+  #  BIT0 indicates if DMA is supported<BR>
+  #  BIT1 indicates if only slave DMA is supported<BR>
+  #  BIT2 indicates if ISA memory is supported<BR>
+  #  Other BITs are reseved and must be zero.
+  #  If more than one features are supported, the different BIT will be enabled at the same time.
+  # @Prompt ISA Bus Features
+  # @Expression 0x80000002 | (gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0
+  gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040
+
+  gBoardModuleTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x00010037
+
+[Protocols]
+  ##
+  ## IntelFrameworkModulePkg
+  ##
+  gEfiOemBadgingProtocolGuid                       = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }}

+ 205 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c

@@ -0,0 +1,205 @@
+/** @file
+  Component name for the QEMU video controller.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gQemuVideoComponentName = {
+  QemuVideoComponentNameGetDriverName,
+  QemuVideoComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gQemuVideoComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) QemuVideoComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) QemuVideoComponentNameGetControllerName,
+  "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mQemuVideoDriverNameTable[] = {
+  { "eng;en", L"QEMU Video Driver" },
+  { NULL , NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mQemuVideoControllerNameTable[] = {
+  { "eng;en", L"QEMU Video PCI Adapter" },
+  { NULL , NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mQemuVideoDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gQemuVideoComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  EFI_STATUS                      Status;
+
+  //
+  // This is a device driver, so ChildHandle must be NULL.
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this driver is currently managing ControllHandle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             gQemuVideoDriverBinding.DriverBindingHandle,
+             &gEfiPciIoProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get the QEMU Video's Device structure
+  //
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mQemuVideoControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This == &gQemuVideoComponentName)
+           );
+}

+ 1011 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c

@@ -0,0 +1,1011 @@
+/** @file
+  This driver is a sample implementation of the Graphics Output Protocol for
+  the QEMU (Cirrus Logic 5446) video controller.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+#include <IndustryStandard/Acpi.h>
+
+EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
+  QemuVideoControllerDriverSupported,
+  QemuVideoControllerDriverStart,
+  QemuVideoControllerDriverStop,
+  0x10,
+  NULL,
+  NULL
+};
+
+QEMU_VIDEO_CARD gQemuVideoCardList[] = {
+    {
+        PCI_CLASS_DISPLAY_VGA,
+        CIRRUS_LOGIC_VENDOR_ID,
+        CIRRUS_LOGIC_5430_DEVICE_ID,
+        QEMU_VIDEO_CIRRUS_5430,
+        L"Cirrus 5430"
+    },{
+        PCI_CLASS_DISPLAY_VGA,
+        CIRRUS_LOGIC_VENDOR_ID,
+        CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,
+        QEMU_VIDEO_CIRRUS_5430,
+        L"Cirrus 5430"
+    },{
+        PCI_CLASS_DISPLAY_VGA,
+        CIRRUS_LOGIC_VENDOR_ID,
+        CIRRUS_LOGIC_5446_DEVICE_ID,
+        QEMU_VIDEO_CIRRUS_5446,
+        L"Cirrus 5446"
+    },{
+        PCI_CLASS_DISPLAY_VGA,
+        0x4321,
+        0x1111,
+        QEMU_VIDEO_BOCHS_MMIO,
+        L"QEMU Standard VGA"
+    },{
+        PCI_CLASS_DISPLAY_OTHER,
+        0x1234,
+        0x1111,
+        QEMU_VIDEO_BOCHS_MMIO,
+        L"QEMU Standard VGA (secondary)"
+    },{
+        PCI_CLASS_DISPLAY_VGA,
+        0x1b36,
+        0x0100,
+        QEMU_VIDEO_BOCHS,
+        L"QEMU QXL VGA"
+    },{
+        PCI_CLASS_DISPLAY_VGA,
+        0x1af4,
+        0x1050,
+        QEMU_VIDEO_BOCHS_MMIO,
+        L"QEMU VirtIO VGA"
+    },{
+        0 /* end of list */
+    }
+};
+
+static QEMU_VIDEO_CARD*
+QemuVideoDetect(
+  IN UINT8 SubClass,
+  IN UINT16 VendorId,
+  IN UINT16 DeviceId
+  )
+{
+  UINTN Index = 0;
+
+  while (gQemuVideoCardList[Index].VendorId != 0) {
+    if (gQemuVideoCardList[Index].SubClass == SubClass &&
+        gQemuVideoCardList[Index].VendorId == VendorId &&
+        gQemuVideoCardList[Index].DeviceId == DeviceId) {
+      return gQemuVideoCardList + Index;
+    }
+    Index++;
+  }
+  return NULL;
+}
+
+/**
+  Check if this device is supported.
+
+  @param  This                   The driver binding protocol.
+  @param  Controller             The controller handle to check.
+  @param  RemainingDevicePath    The remaining device path.
+
+  @retval EFI_SUCCESS            The bus supports this controller.
+  @retval EFI_UNSUPPORTED        This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+  QEMU_VIDEO_CARD     *Card;
+
+  //
+  // Open the PCI I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Read the PCI Configuration Header from the PCI Device
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  Status = EFI_UNSUPPORTED;
+  if (!IS_PCI_DISPLAY (&Pci)) {
+    goto Done;
+  }
+  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
+  if (Card != NULL) {
+    DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));
+    Status = EFI_SUCCESS;
+  }
+
+Done:
+  //
+  // Close the PCI I/O Protocol
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiPciIoProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  return Status;
+}
+
+/**
+  Start to process the controller.
+
+  @param  This                   The USB bus driver binding instance.
+  @param  Controller             The controller to check.
+  @param  RemainingDevicePath    The remaining device patch.
+
+  @retval EFI_SUCCESS            The controller is controlled by the usb bus.
+  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb
+                                 bus.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_TPL                           OldTpl;
+  EFI_STATUS                        Status;
+  QEMU_VIDEO_PRIVATE_DATA           *Private;
+  BOOLEAN                           IsQxl;
+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
+  ACPI_ADR_DEVICE_PATH              AcpiDeviceNode;
+  PCI_TYPE00                        Pci;
+  QEMU_VIDEO_CARD                   *Card;
+  EFI_PCI_IO_PROTOCOL               *ChildPciIo;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  //
+  // Allocate Private context data for GOP inteface.
+  //
+  Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));
+  if (Private == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto RestoreTpl;
+  }
+
+  //
+  // Set up context record
+  //
+  Private->Signature  = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;
+
+  //
+  // Open PCI I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &Private->PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreePrivate;
+  }
+
+  //
+  // Read the PCI Configuration Header from the PCI Device
+  //
+  Status = Private->PciIo->Pci.Read (
+                        Private->PciIo,
+                        EfiPciIoWidthUint32,
+                        0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    goto ClosePciIo;
+  }
+
+  //
+  // Determine card variant.
+  //
+  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
+  if (Card == NULL) {
+    Status = EFI_DEVICE_ERROR;
+    goto ClosePciIo;
+  }
+  Private->Variant = Card->Variant;
+
+  //
+  // IsQxl is based on the detected Card->Variant, which at a later point might
+  // not match Private->Variant.
+  //
+  IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);
+
+  //
+  // Save original PCI attributes
+  //
+  Status = Private->PciIo->Attributes (
+                    Private->PciIo,
+                    EfiPciIoAttributeOperationGet,
+                    0,
+                    &Private->OriginalPciAttributes
+                    );
+
+  if (EFI_ERROR (Status)) {
+    goto ClosePciIo;
+  }
+
+  //
+  // Set new PCI attributes
+  //
+  Status = Private->PciIo->Attributes (
+                            Private->PciIo,
+                            EfiPciIoAttributeOperationEnable,
+                            EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+                            NULL
+                            );
+  if (EFI_ERROR (Status)) {
+    goto ClosePciIo;
+  }
+
+  //
+  // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).
+  //
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+    EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
+
+    Status = Private->PciIo->GetBarAttributes (
+                        Private->PciIo,
+                        PCI_BAR_IDX2,
+                        NULL,
+                        (VOID**) &MmioDesc
+                        );
+    if (EFI_ERROR (Status) ||
+        MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+      DEBUG ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));
+      Private->Variant = QEMU_VIDEO_BOCHS;
+    } else {
+      DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",
+              MmioDesc->AddrRangeMin));
+    }
+
+    if (!EFI_ERROR (Status)) {
+      FreePool (MmioDesc);
+    }
+  }
+
+  //
+  // Check if accessing the bochs interface works.
+  //
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
+      Private->Variant == QEMU_VIDEO_BOCHS) {
+    UINT16 BochsId;
+    BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);
+    if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {
+      DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));
+      Status = EFI_DEVICE_ERROR;
+      goto RestoreAttributes;
+    }
+  }
+
+  //
+  // Get ParentDevicePath
+  //
+  Status = gBS->HandleProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    goto RestoreAttributes;
+  }
+
+  //
+  // Set Gop Device Path
+  //
+  ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
+  SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+  Private->GopDevicePath = AppendDevicePathNode (
+                                      ParentDevicePath,
+                                      (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+                                      );
+  if (Private->GopDevicePath == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto RestoreAttributes;
+  }
+
+  //
+  // Create new child handle and install the device path protocol on it.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  Private->GopDevicePath,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreeGopDevicePath;
+  }
+
+  //
+  // Construct video mode buffer
+  //
+  switch (Private->Variant) {
+  case QEMU_VIDEO_CIRRUS_5430:
+  case QEMU_VIDEO_CIRRUS_5446:
+    Status = QemuVideoCirrusModeSetup (Private);
+    break;
+  case QEMU_VIDEO_BOCHS_MMIO:
+  case QEMU_VIDEO_BOCHS:
+    Status = QemuVideoBochsModeSetup (Private, IsQxl);
+    break;
+  default:
+    ASSERT (FALSE);
+    Status = EFI_DEVICE_ERROR;
+    break;
+  }
+  if (EFI_ERROR (Status)) {
+    goto UninstallGopDevicePath;
+  }
+
+  //
+  // Start the GOP software stack.
+  //
+  Status = QemuVideoGraphicsOutputConstructor (Private);
+  if (EFI_ERROR (Status)) {
+    goto FreeModeData;
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->Handle,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  &Private->GraphicsOutput,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto DestructQemuVideoGraphics;
+  }
+
+  //
+  // Reference parent handle from child handle.
+  //
+  Status = gBS->OpenProtocol (
+                Controller,
+                &gEfiPciIoProtocolGuid,
+                (VOID **) &ChildPciIo,
+                This->DriverBindingHandle,
+                Private->Handle,
+                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                );
+  if (EFI_ERROR (Status)) {
+    goto UninstallGop;
+  }
+
+#if defined MDE_CPU_IA32 || defined MDE_CPU_X64
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
+      Private->Variant == QEMU_VIDEO_BOCHS) {
+    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+  }
+#endif
+
+  gBS->RestoreTPL (OldTpl);
+  return EFI_SUCCESS;
+
+UninstallGop:
+  gBS->UninstallProtocolInterface (Private->Handle,
+         &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
+
+DestructQemuVideoGraphics:
+  QemuVideoGraphicsOutputDestructor (Private);
+
+FreeModeData:
+  FreePool (Private->ModeData);
+
+UninstallGopDevicePath:
+  gBS->UninstallProtocolInterface (Private->Handle,
+         &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
+
+FreeGopDevicePath:
+  FreePool (Private->GopDevicePath);
+
+RestoreAttributes:
+  Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
+                    Private->OriginalPciAttributes, NULL);
+
+ClosePciIo:
+  gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, Controller);
+
+FreePrivate:
+  FreePool (Private);
+
+RestoreTpl:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+  Stop this device
+
+  @param  This                   The USB bus driver binding protocol.
+  @param  Controller             The controller to release.
+  @param  NumberOfChildren       The number of children of this device that
+                                 opened the controller BY_CHILD.
+  @param  ChildHandleBuffer      The array of child handle.
+
+  @retval EFI_SUCCESS            The controller or children are stopped.
+  @retval EFI_DEVICE_ERROR       Failed to stop the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN UINTN                          NumberOfChildren,
+  IN EFI_HANDLE                     *ChildHandleBuffer
+  )
+{
+  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
+
+  EFI_STATUS                      Status;
+  QEMU_VIDEO_PRIVATE_DATA  *Private;
+
+  if (NumberOfChildren == 0) {
+    //
+    // Close the PCI I/O Protocol
+    //
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    return EFI_SUCCESS;
+  }
+
+  //
+  // free all resources for whose access we need the child handle, because the
+  // child handle is going away
+  //
+  ASSERT (NumberOfChildren == 1);
+  Status = gBS->OpenProtocol (
+                  ChildHandleBuffer[0],
+                  &gEfiGraphicsOutputProtocolGuid,
+                  (VOID **) &GraphicsOutput,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get our private context information
+  //
+  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
+  ASSERT (Private->Handle == ChildHandleBuffer[0]);
+
+  QemuVideoGraphicsOutputDestructor (Private);
+  //
+  // Remove the GOP protocol interface from the system
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Private->Handle,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  &Private->GraphicsOutput,
+                  NULL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Restore original PCI attributes
+  //
+  Private->PciIo->Attributes (
+                  Private->PciIo,
+                  EfiPciIoAttributeOperationSet,
+                  Private->OriginalPciAttributes,
+                  NULL
+                  );
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiPciIoProtocolGuid,
+        This->DriverBindingHandle,
+        Private->Handle
+        );
+
+  FreePool (Private->ModeData);
+  gBS->UninstallProtocolInterface (Private->Handle,
+         &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
+  FreePool (Private->GopDevicePath);
+
+  //
+  // Free our instance data
+  //
+  gBS->FreePool (Private);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  Address TODO: add argument description
+  @param  Data TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+outb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address,
+  UINT8                           Data
+  )
+{
+  EFI_STATUS          Status;
+  VOID                *Interface;
+  Private->PciIo->Io.Write (
+                      Private->PciIo,
+                      EfiPciIoWidthUint8,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      Address,
+                      1,
+                      &Data
+                      );
+  Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
+  if (!EFI_ERROR(Status)) {
+    return;
+  }
+
+  Status = S3BootScriptSaveIoWrite(
+      S3BootScriptWidthUint8,
+      Address,
+      (UINTN)1,
+      &Data
+  );
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  Address TODO: add argument description
+  @param  Data TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+outw (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address,
+  UINT16                          Data
+  )
+{
+  EFI_STATUS          Status;
+  VOID                *Interface;
+
+  Private->PciIo->Io.Write (
+                      Private->PciIo,
+                      EfiPciIoWidthUint16,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      Address,
+                      1,
+                      &Data
+                      );
+
+  Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
+  if (!EFI_ERROR(Status)) {
+    return;
+  }
+  Status = S3BootScriptSaveIoWrite(
+      S3BootScriptWidthUint16,
+      Address,
+      1,
+      &Data
+  );
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  Address TODO: add argument description
+
+  TODO: add return values
+
+**/
+UINT8
+inb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address
+  )
+{
+  UINT8 Data;
+
+  Private->PciIo->Io.Read (
+                      Private->PciIo,
+                      EfiPciIoWidthUint8,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      Address,
+                      1,
+                      &Data
+                      );
+  return Data;
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  Address TODO: add argument description
+
+  TODO: add return values
+
+**/
+UINT16
+inw (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address
+  )
+{
+  UINT16  Data;
+
+  Private->PciIo->Io.Read (
+                      Private->PciIo,
+                      EfiPciIoWidthUint16,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      Address,
+                      1,
+                      &Data
+                      );
+  return Data;
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  Index TODO: add argument description
+  @param  Red TODO: add argument description
+  @param  Green TODO: add argument description
+  @param  Blue TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+SetPaletteColor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Index,
+  UINT8                           Red,
+  UINT8                           Green,
+  UINT8                           Blue
+  )
+{
+  VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
+  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
+  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
+  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+SetDefaultPalette (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  )
+{
+  UINTN Index;
+  UINTN RedIndex;
+  UINTN GreenIndex;
+  UINTN BlueIndex;
+
+  Index = 0;
+  for (RedIndex = 0; RedIndex < 8; RedIndex++) {
+    for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
+      for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
+        SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
+        Index++;
+      }
+    }
+  }
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+ClearScreen (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  )
+{
+  UINT32  Color;
+
+  Color = 0;
+  Private->PciIo->Mem.Write (
+                        Private->PciIo,
+                        EfiPciIoWidthFillUint32,
+                        0,
+                        0,
+                        0x400000 >> 2,
+                        &Color
+                        );
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+DrawLogo (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           ScreenWidth,
+  UINTN                           ScreenHeight
+  )
+{
+}
+
+/**
+  TODO: Add function description
+
+  @param  Private TODO: add argument description
+  @param  ModeData TODO: add argument description
+
+  TODO: add return values
+
+**/
+VOID
+InitializeCirrusGraphicsMode (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  QEMU_VIDEO_CIRRUS_MODES  *ModeData
+  )
+{
+  UINT8 Byte;
+  UINTN Index;
+
+  outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
+  outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
+
+  for (Index = 0; Index < 15; Index++) {
+    outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
+  }
+
+  if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
+    outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
+    Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
+    outb (Private, SEQ_DATA_REGISTER, Byte);
+  }
+
+  outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
+  outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
+  outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
+  outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
+
+  for (Index = 0; Index < 28; Index++) {
+    outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
+  }
+
+  for (Index = 0; Index < 9; Index++) {
+    outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
+  }
+
+  inb (Private, INPUT_STATUS_1_REGISTER);
+
+  for (Index = 0; Index < 21; Index++) {
+    outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
+    outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
+  }
+
+  outb (Private, ATT_ADDRESS_REGISTER, 0x20);
+
+  outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
+  outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
+  outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
+  outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
+
+  SetDefaultPalette (Private);
+  ClearScreen (Private);
+}
+
+VOID
+BochsWrite (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINT16                   Reg,
+  UINT16                   Data
+  )
+{
+  EFI_STATUS   Status;
+
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+    Status = Private->PciIo->Mem.Write (
+        Private->PciIo,
+        EfiPciIoWidthUint16,
+        PCI_BAR_IDX2,
+        0x500 + (Reg << 1),
+        1,
+        &Data
+        );
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
+    outw (Private, VBE_DISPI_IOPORT_DATA,  Data);
+  }
+}
+
+UINT16
+BochsRead (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINT16                   Reg
+  )
+{
+  EFI_STATUS   Status;
+  UINT16       Data;
+
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+    Status = Private->PciIo->Mem.Read (
+        Private->PciIo,
+        EfiPciIoWidthUint16,
+        PCI_BAR_IDX2,
+        0x500 + (Reg << 1),
+        1,
+        &Data
+        );
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
+    Data = inw (Private, VBE_DISPI_IOPORT_DATA);
+  }
+  return Data;
+}
+
+VOID
+VgaOutb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                    Reg,
+  UINT8                    Data
+  )
+{
+  EFI_STATUS   Status;
+
+  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+    Status = Private->PciIo->Mem.Write (
+        Private->PciIo,
+        EfiPciIoWidthUint8,
+        PCI_BAR_IDX2,
+        0x400 - 0x3c0 + Reg,
+        1,
+        &Data
+        );
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    outb (Private, Reg, Data);
+  }
+}
+
+VOID
+InitializeBochsGraphicsMode (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  QEMU_VIDEO_BOCHS_MODES  *ModeData
+  )
+{
+  DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
+          ModeData->Width, ModeData->Height, ModeData->ColorDepth));
+
+  /* unblank */
+  VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
+
+  BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,      0);
+  BochsWrite (Private, VBE_DISPI_INDEX_BANK,        0);
+  BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET,    0);
+  BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET,    0);
+
+  BochsWrite (Private, VBE_DISPI_INDEX_BPP,         (UINT16) ModeData->ColorDepth);
+  BochsWrite (Private, VBE_DISPI_INDEX_XRES,        (UINT16) ModeData->Width);
+  BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH,  (UINT16) ModeData->Width);
+  BochsWrite (Private, VBE_DISPI_INDEX_YRES,        (UINT16) ModeData->Height);
+  BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
+
+  BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
+              VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+
+  SetDefaultPalette (Private);
+  ClearScreen (Private);
+}
+
+EFI_STATUS
+EFIAPI
+InitializeQemuVideo (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gQemuVideoDriverBinding,
+             ImageHandle,
+             &gQemuVideoComponentName,
+             &gQemuVideoComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install EFI Driver Supported EFI Version Protocol required for
+  // EFI drivers that are on PCI and other plug in cards.
+  //
+  gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiDriverSupportedEfiVersionProtocolGuid,
+                  &gQemuVideoDriverSupportedEfiVersion,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}

+ 15 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c

@@ -0,0 +1,15 @@
+/** @file
+  Driver supported version protocol for the QEMU video driver.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gQemuVideoDriverSupportedEfiVersion = {
+  sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure.
+  0                                                   // Version number to be filled at start up.
+};
+

+ 416 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c

@@ -0,0 +1,416 @@
+/** @file
+  Graphics Output Protocol functions for the QEMU video controller.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+STATIC
+VOID
+QemuVideoCompleteModeInfo (
+  IN  QEMU_VIDEO_MODE_DATA           *ModeData,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
+  )
+{
+  Info->Version = 0;
+  if (ModeData->ColorDepth == 8) {
+    Info->PixelFormat = PixelBitMask;
+    Info->PixelInformation.RedMask = PIXEL_RED_MASK;
+    Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
+    Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
+    Info->PixelInformation.ReservedMask = 0;
+  } else if (ModeData->ColorDepth == 24) {
+    Info->PixelFormat = PixelBitMask;
+    Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
+    Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
+    Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
+    Info->PixelInformation.ReservedMask = 0;
+  } else if (ModeData->ColorDepth == 32) {
+    DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
+    Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+  }
+  Info->PixelsPerScanLine = Info->HorizontalResolution;
+}
+
+
+STATIC
+EFI_STATUS
+QemuVideoCompleteModeData (
+  IN  QEMU_VIDEO_PRIVATE_DATA           *Private,
+  OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
+  )
+{
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
+  QEMU_VIDEO_MODE_DATA           *ModeData;
+
+  ModeData = &Private->ModeData[Mode->Mode];
+  Info = Mode->Info;
+  QemuVideoCompleteModeInfo (ModeData, Info);
+
+  Private->PciIo->GetBarAttributes (
+                        Private->PciIo,
+                        0,
+                        NULL,
+                        (VOID**) &FrameBufDesc
+                        );
+
+  Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
+  Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
+  Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
+  Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
+                            EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
+                            );
+  DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
+    Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
+
+  FreePool (FrameBufDesc);
+  return EFI_SUCCESS;
+}
+
+//
+// Graphics Output Protocol Member Functions
+//
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputQueryMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  UINT32                                ModeNumber,
+  OUT UINTN                                 *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
+  )
+/*++
+
+Routine Description:
+
+  Graphics Output protocol interface to query video mode
+
+  Arguments:
+    This                  - Protocol instance pointer.
+    ModeNumber            - The mode number to return information on.
+    Info                  - Caller allocated buffer that returns information about ModeNumber.
+    SizeOfInfo            - A pointer to the size, in bytes, of the Info buffer.
+
+  Returns:
+    EFI_SUCCESS           - Mode information returned.
+    EFI_BUFFER_TOO_SMALL  - The Info buffer was too small.
+    EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.
+    EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()
+    EFI_INVALID_PARAMETER - One of the input args was NULL.
+
+--*/
+{
+  QEMU_VIDEO_PRIVATE_DATA  *Private;
+  QEMU_VIDEO_MODE_DATA     *ModeData;
+
+  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+  if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (*Info == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  ModeData = &Private->ModeData[ModeNumber];
+  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
+  QemuVideoCompleteModeInfo (ModeData, *Info);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputSetMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+  IN  UINT32                       ModeNumber
+  )
+/*++
+
+Routine Description:
+
+  Graphics Output protocol interface to set video mode
+
+  Arguments:
+    This             - Protocol instance pointer.
+    ModeNumber       - The mode number to be set.
+
+  Returns:
+    EFI_SUCCESS      - Graphics mode was changed.
+    EFI_DEVICE_ERROR - The device had an error and could not complete the request.
+    EFI_UNSUPPORTED  - ModeNumber is not supported by this device.
+
+--*/
+{
+  QEMU_VIDEO_PRIVATE_DATA       *Private;
+  QEMU_VIDEO_MODE_DATA          *ModeData;
+  RETURN_STATUS                 Status;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
+
+  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+  if (ModeNumber >= This->Mode->MaxMode) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ModeData = &Private->ModeData[ModeNumber];
+
+  switch (Private->Variant) {
+  case QEMU_VIDEO_CIRRUS_5430:
+  case QEMU_VIDEO_CIRRUS_5446:
+    InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
+    break;
+  case QEMU_VIDEO_BOCHS_MMIO:
+  case QEMU_VIDEO_BOCHS:
+    InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
+    break;
+  default:
+    ASSERT (FALSE);
+    return EFI_DEVICE_ERROR;
+  }
+
+  This->Mode->Mode = ModeNumber;
+  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  QemuVideoCompleteModeData (Private, This->Mode);
+
+  //
+  // Re-initialize the frame buffer configure when mode changes.
+  //
+  Status = FrameBufferBltConfigure (
+             (VOID*) (UINTN) This->Mode->FrameBufferBase,
+             This->Mode->Info,
+             Private->FrameBufferBltConfigure,
+             &Private->FrameBufferBltConfigureSize
+             );
+  if (Status == RETURN_BUFFER_TOO_SMALL) {
+    //
+    // Frame buffer configure may be larger in new mode.
+    //
+    if (Private->FrameBufferBltConfigure != NULL) {
+      FreePool (Private->FrameBufferBltConfigure);
+    }
+    Private->FrameBufferBltConfigure =
+      AllocatePool (Private->FrameBufferBltConfigureSize);
+    ASSERT (Private->FrameBufferBltConfigure != NULL);
+
+    //
+    // Create the configuration for FrameBufferBltLib
+    //
+    Status = FrameBufferBltConfigure (
+                (VOID*) (UINTN) This->Mode->FrameBufferBase,
+                This->Mode->Info,
+                Private->FrameBufferBltConfigure,
+                &Private->FrameBufferBltConfigureSize
+                );
+  }
+  ASSERT (Status == RETURN_SUCCESS);
+
+  //
+  // Per UEFI Spec, need to clear the visible portions of the output display to black.
+  //
+  ZeroMem (&Black, sizeof (Black));
+  Status = FrameBufferBlt (
+             Private->FrameBufferBltConfigure,
+             &Black,
+             EfiBltVideoFill,
+             0, 0,
+             0, 0,
+             This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution,
+             0
+             );
+  ASSERT_RETURN_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputBlt (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
+  IN  UINTN                                 SourceX,
+  IN  UINTN                                 SourceY,
+  IN  UINTN                                 DestinationX,
+  IN  UINTN                                 DestinationY,
+  IN  UINTN                                 Width,
+  IN  UINTN                                 Height,
+  IN  UINTN                                 Delta
+  )
+/*++
+
+Routine Description:
+
+  Graphics Output protocol instance to block transfer for CirrusLogic device
+
+Arguments:
+
+  This          - Pointer to Graphics Output protocol instance
+  BltBuffer     - The data to transfer to screen
+  BltOperation  - The operation to perform
+  SourceX       - The X coordinate of the source for BltOperation
+  SourceY       - The Y coordinate of the source for BltOperation
+  DestinationX  - The X coordinate of the destination for BltOperation
+  DestinationY  - The Y coordinate of the destination for BltOperation
+  Width         - The width of a rectangle in the blt rectangle in pixels
+  Height        - The height of a rectangle in the blt rectangle in pixels
+  Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+                  If a Delta of 0 is used, the entire BltBuffer will be operated on.
+                  If a subrectangle of the BltBuffer is used, then Delta represents
+                  the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+  EFI_INVALID_PARAMETER - Invalid parameter passed in
+  EFI_SUCCESS - Blt operation success
+
+--*/
+{
+  EFI_STATUS                      Status;
+  EFI_TPL                         OriginalTPL;
+  QEMU_VIDEO_PRIVATE_DATA         *Private;
+
+  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+  //
+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+  // We would not want a timer based event (Cursor, ...) to come in while we are
+  // doing this operation.
+  //
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+  switch (BltOperation) {
+  case EfiBltVideoToBltBuffer:
+  case EfiBltBufferToVideo:
+  case EfiBltVideoFill:
+  case EfiBltVideoToVideo:
+    Status = FrameBufferBlt (
+      Private->FrameBufferBltConfigure,
+      BltBuffer,
+      BltOperation,
+      SourceX,
+      SourceY,
+      DestinationX,
+      DestinationY,
+      Width,
+      Height,
+      Delta
+      );
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  gBS->RestoreTPL (OriginalTPL);
+
+  return Status;
+}
+
+EFI_STATUS
+QemuVideoGraphicsOutputConstructor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+
+  GraphicsOutput            = &Private->GraphicsOutput;
+  GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
+  GraphicsOutput->SetMode   = QemuVideoGraphicsOutputSetMode;
+  GraphicsOutput->Blt       = QemuVideoGraphicsOutputBlt;
+
+  //
+  // Initialize the private data
+  //
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData,
+                  sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
+                  (VOID **) &Private->GraphicsOutput.Mode
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData,
+                  sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+                  (VOID **) &Private->GraphicsOutput.Mode->Info
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreeMode;
+  }
+  Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
+  Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+  Private->FrameBufferBltConfigure      = NULL;
+  Private->FrameBufferBltConfigureSize  = 0;
+
+  //
+  // Initialize the hardware
+  //
+  Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
+  if (EFI_ERROR (Status)) {
+    goto FreeInfo;
+  }
+
+  DrawLogo (
+    Private,
+    Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
+    Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
+    );
+
+  return EFI_SUCCESS;
+
+FreeInfo:
+  FreePool (Private->GraphicsOutput.Mode->Info);
+
+FreeMode:
+  FreePool (Private->GraphicsOutput.Mode);
+  Private->GraphicsOutput.Mode = NULL;
+
+  return Status;
+}
+
+EFI_STATUS
+QemuVideoGraphicsOutputDestructor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+  None
+
+--*/
+{
+  if (Private->FrameBufferBltConfigure != NULL) {
+    FreePool (Private->FrameBufferBltConfigure);
+  }
+
+  if (Private->GraphicsOutput.Mode != NULL) {
+    if (Private->GraphicsOutput.Mode->Info != NULL) {
+      gBS->FreePool (Private->GraphicsOutput.Mode->Info);
+    }
+    gBS->FreePool (Private->GraphicsOutput.Mode);
+  }
+
+  return EFI_SUCCESS;
+}
+
+

+ 341 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c

@@ -0,0 +1,341 @@
+/** @file
+  Graphics Output Protocol functions for the QEMU video controller.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+
+///
+/// Generic Attribute Controller Register Settings
+///
+UINT8  AttributeController[21] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+  0x41, 0x00, 0x0F, 0x00, 0x00
+};
+
+///
+/// Generic Graphics Controller Register Settings
+///
+UINT8 GraphicsController[9] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
+};
+
+//
+// 640 x 480 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_640_480_256_60[28] = {
+  0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+  0xff, 0x00, 0x00, 0x22
+};
+
+UINT8 Crtc_640_480_32bpp_60[28] = {
+  0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,
+  0xff, 0x00, 0x00, 0x32
+};
+
+UINT16 Seq_640_480_256_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
+};
+
+UINT16 Seq_640_480_32bpp_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
+};
+
+//
+// 800 x 600 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_800_600_256_60[28] = {
+  0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+  0xFF, 0x00, 0x00, 0x22
+};
+
+UINT8 Crtc_800_600_32bpp_60[28] = {
+  0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,
+  0xFF, 0x00, 0x00, 0x32
+};
+
+UINT16 Seq_800_600_256_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
+};
+
+UINT16 Seq_800_600_32bpp_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
+};
+
+UINT8 Crtc_960_720_32bpp_60[28] = {
+  0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
+  0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_960_720_32bpp_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+//
+// 1024 x 768 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_1024_768_256_60[28] = {
+  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+  0xFF, 0x4A, 0x00, 0x22
+};
+
+UINT16 Seq_1024_768_256_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+//
+// 1024 x 768 x 24-bit color @ 60 Hertz
+//
+UINT8 Crtc_1024_768_24bpp_60[28] = {
+  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+  0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_1024_768_24bpp_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+UINT8 Crtc_1024_768_32bpp_60[28] = {
+  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
+  0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_1024_768_32bpp_60[15] = {
+  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+///
+/// Table of supported video modes
+///
+QEMU_VIDEO_CIRRUS_MODES  QemuVideoCirrusModes[] = {
+//  {  640, 480, 8, Crtc_640_480_256_60,  Seq_640_480_256_60,  0xe3 },
+//  {  800, 600, 8, Crtc_800_600_256_60,  Seq_800_600_256_60,  0xef },
+  {  640, 480, 32, Crtc_640_480_32bpp_60,  Seq_640_480_32bpp_60,  0xef },
+  {  800, 600, 32, Crtc_800_600_32bpp_60,  Seq_800_600_32bpp_60,  0xef },
+//  { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
+  { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }
+//  { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
+//  { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
+};
+
+#define QEMU_VIDEO_CIRRUS_MODE_COUNT \
+  (ARRAY_SIZE (QemuVideoCirrusModes))
+
+/**
+  Construct the valid video modes for QemuVideo.
+
+**/
+EFI_STATUS
+QemuVideoCirrusModeSetup (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  )
+{
+  UINT32                                 Index;
+  QEMU_VIDEO_MODE_DATA                   *ModeData;
+  QEMU_VIDEO_CIRRUS_MODES                *VideoMode;
+
+  //
+  // Setup Video Modes
+  //
+  Private->ModeData = AllocatePool (
+                        sizeof (Private->ModeData[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT
+                        );
+  if (Private->ModeData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ModeData = Private->ModeData;
+  VideoMode = &QemuVideoCirrusModes[0];
+  for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {
+    ModeData->InternalModeIndex = Index;
+    ModeData->HorizontalResolution          = VideoMode->Width;
+    ModeData->VerticalResolution            = VideoMode->Height;
+    ModeData->ColorDepth                    = VideoMode->ColorDepth;
+    DEBUG ((EFI_D_INFO,
+      "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",
+      (INT32) (ModeData - Private->ModeData),
+      ModeData->InternalModeIndex,
+      ModeData->HorizontalResolution,
+      ModeData->VerticalResolution,
+      ModeData->ColorDepth
+      ));
+
+    ModeData ++ ;
+    VideoMode ++;
+  }
+  Private->MaxMode = ModeData - Private->ModeData;
+
+  return EFI_SUCCESS;
+}
+
+///
+/// Table of supported video modes
+///
+QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {
+  {  640,  480, 32 },
+  {  800,  480, 32 },
+  {  800,  600, 32 },
+  {  832,  624, 32 },
+  {  960,  640, 32 },
+  { 1024,  600, 32 },
+  { 1024,  768, 32 },
+  { 1152,  864, 32 },
+  { 1152,  870, 32 },
+  { 1280,  720, 32 },
+  { 1280,  760, 32 },
+  { 1280,  768, 32 },
+  { 1280,  800, 32 },
+  { 1280,  960, 32 },
+  { 1280, 1024, 32 },
+  { 1360,  768, 32 },
+  { 1366,  768, 32 },
+  { 1400, 1050, 32 },
+  { 1440,  900, 32 },
+  { 1600,  900, 32 },
+  { 1600, 1200, 32 },
+  { 1680, 1050, 32 },
+  { 1920, 1080, 32 },
+  { 1920, 1200, 32 },
+  { 1920, 1440, 32 },
+  { 2000, 2000, 32 },
+  { 2048, 1536, 32 },
+  { 2048, 2048, 32 },
+  { 2560, 1440, 32 },
+  { 2560, 1600, 32 },
+  { 2560, 2048, 32 },
+  { 2800, 2100, 32 },
+  { 3200, 2400, 32 },
+  { 3840, 2160, 32 },
+  { 4096, 2160, 32 },
+  { 7680, 4320, 32 },
+  { 8192, 4320, 32 }
+};
+
+#define QEMU_VIDEO_BOCHS_MODE_COUNT \
+  (ARRAY_SIZE (QemuVideoBochsModes))
+
+EFI_STATUS
+QemuVideoBochsModeSetup (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  BOOLEAN                  IsQxl
+  )
+{
+  UINT32                                 AvailableFbSize;
+  UINT32                                 Index;
+  QEMU_VIDEO_MODE_DATA                   *ModeData;
+  QEMU_VIDEO_BOCHS_MODES                 *VideoMode;
+
+  //
+  // Fetch the available framebuffer size.
+  //
+  // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the
+  // drawable framebuffer. Up to and including qemu-2.1 however it used to
+  // return the size of PCI BAR 0 (ie. the full video RAM size).
+  //
+  // On stdvga the two concepts coincide with each other; the full memory size
+  // is usable for drawing.
+  //
+  // On QXL however, only a leading segment, "surface 0", can be used for
+  // drawing; the rest of the video memory is used for the QXL guest-host
+  // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of
+  // "surface 0", but since it doesn't (up to and including qemu-2.1), we
+  // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
+  // where it is also available.
+  //
+  if (IsQxl) {
+    UINT32 Signature;
+    UINT32 DrawStart;
+
+    Signature = 0;
+    DrawStart = 0xFFFFFFFF;
+    AvailableFbSize = 0;
+    if (EFI_ERROR (
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+                                PCI_BAR_IDX2, 0, 1, &Signature)) ||
+        Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||
+        EFI_ERROR (
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+                                PCI_BAR_IDX2, 36, 1, &DrawStart)) ||
+        DrawStart != 0 ||
+        EFI_ERROR (
+          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+                                PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {
+      DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "
+        "ROM\n", __FUNCTION__));
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    AvailableFbSize  = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
+    AvailableFbSize *= SIZE_64KB;
+  }
+  DEBUG ((EFI_D_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,
+    AvailableFbSize));
+
+  //
+  // Setup Video Modes
+  //
+  Private->ModeData = AllocatePool (
+                        sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT
+                        );
+  if (Private->ModeData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ModeData = Private->ModeData;
+  VideoMode = &QemuVideoBochsModes[0];
+  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {
+    UINTN RequiredFbSize;
+
+    ASSERT (VideoMode->ColorDepth % 8 == 0);
+    RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *
+                     (VideoMode->ColorDepth / 8);
+    if (RequiredFbSize <= AvailableFbSize) {
+      ModeData->InternalModeIndex    = Index;
+      ModeData->HorizontalResolution = VideoMode->Width;
+      ModeData->VerticalResolution   = VideoMode->Height;
+      ModeData->ColorDepth           = VideoMode->ColorDepth;
+      DEBUG ((EFI_D_INFO,
+        "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",
+        (INT32) (ModeData - Private->ModeData),
+        ModeData->InternalModeIndex,
+        ModeData->HorizontalResolution,
+        ModeData->VerticalResolution,
+        ModeData->ColorDepth
+        ));
+
+      ModeData ++ ;
+    }
+    VideoMode ++;
+  }
+  Private->MaxMode = ModeData - Private->ModeData;
+
+  return EFI_SUCCESS;
+}
+

+ 507 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h

@@ -0,0 +1,507 @@
+/** @file
+  QEMU Video Controller Driver
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// QEMU Video Controller Driver
+//
+
+#ifndef _QEMU_H_
+#define _QEMU_H_
+
+
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/TimerLib.h>
+#include <Library/FrameBufferBltLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Library/S3BootScriptLib.h>
+
+//
+// QEMU Video PCI Configuration Header values
+//
+#define CIRRUS_LOGIC_VENDOR_ID                0x1013
+#define CIRRUS_LOGIC_5430_DEVICE_ID           0x00a8
+#define CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID 0x00a0
+#define CIRRUS_LOGIC_5446_DEVICE_ID           0x00b8
+
+//
+// QEMU Vide Graphical Mode Data
+//
+typedef struct {
+  UINT32  InternalModeIndex; // points into card-specific mode table
+  UINT32  HorizontalResolution;
+  UINT32  VerticalResolution;
+  UINT32  ColorDepth;
+} QEMU_VIDEO_MODE_DATA;
+
+#define PIXEL_RED_SHIFT   0
+#define PIXEL_GREEN_SHIFT 3
+#define PIXEL_BLUE_SHIFT  6
+
+#define PIXEL_RED_MASK    (BIT7 | BIT6 | BIT5)
+#define PIXEL_GREEN_MASK  (BIT4 | BIT3 | BIT2)
+#define PIXEL_BLUE_MASK   (BIT1 | BIT0)
+
+#define PIXEL_TO_COLOR_BYTE(pixel, mask, shift) ((UINT8) ((pixel & mask) << shift))
+#define PIXEL_TO_RED_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_RED_MASK, PIXEL_RED_SHIFT)
+#define PIXEL_TO_GREEN_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_GREEN_MASK, PIXEL_GREEN_SHIFT)
+#define PIXEL_TO_BLUE_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_BLUE_MASK, PIXEL_BLUE_SHIFT)
+
+#define RGB_BYTES_TO_PIXEL(Red, Green, Blue) \
+  (UINT8) ( (((Red) >> PIXEL_RED_SHIFT) & PIXEL_RED_MASK) | \
+            (((Green) >> PIXEL_GREEN_SHIFT) & PIXEL_GREEN_MASK) | \
+            (((Blue) >> PIXEL_BLUE_SHIFT) & PIXEL_BLUE_MASK) )
+
+#define PIXEL24_RED_MASK    0x00ff0000
+#define PIXEL24_GREEN_MASK  0x0000ff00
+#define PIXEL24_BLUE_MASK   0x000000ff
+
+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
+
+//
+// QEMU Video Private Data Structure
+//
+#define QEMU_VIDEO_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('Q', 'V', 'I', 'D')
+
+typedef enum {
+  QEMU_VIDEO_CIRRUS_5430 = 1,
+  QEMU_VIDEO_CIRRUS_5446,
+  QEMU_VIDEO_BOCHS,
+  QEMU_VIDEO_BOCHS_MMIO,
+} QEMU_VIDEO_VARIANT;
+
+typedef struct {
+  UINT8                                 SubClass;
+  UINT16                                VendorId;
+  UINT16                                DeviceId;
+  QEMU_VIDEO_VARIANT                    Variant;
+  CHAR16                                *Name;
+} QEMU_VIDEO_CARD;
+
+typedef struct {
+  UINT64                                Signature;
+  EFI_HANDLE                            Handle;
+  EFI_PCI_IO_PROTOCOL                   *PciIo;
+  UINT64                                OriginalPciAttributes;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL          GraphicsOutput;
+  EFI_DEVICE_PATH_PROTOCOL              *GopDevicePath;
+
+  //
+  // The next two fields match the client-visible
+  // EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.MaxMode field.
+  //
+  UINTN                                 MaxMode;
+  QEMU_VIDEO_MODE_DATA                  *ModeData;
+
+  QEMU_VIDEO_VARIANT                    Variant;
+  FRAME_BUFFER_CONFIGURE                *FrameBufferBltConfigure;
+  UINTN                                 FrameBufferBltConfigureSize;
+} QEMU_VIDEO_PRIVATE_DATA;
+
+///
+/// Card-specific Video Mode structures
+///
+typedef struct {
+  UINT32  Width;
+  UINT32  Height;
+  UINT32  ColorDepth;
+  UINT8   *CrtcSettings;
+  UINT16  *SeqSettings;
+  UINT8   MiscSetting;
+} QEMU_VIDEO_CIRRUS_MODES;
+
+typedef struct {
+  UINT32  Width;
+  UINT32  Height;
+  UINT32  ColorDepth;
+} QEMU_VIDEO_BOCHS_MODES;
+
+#define QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS(a) \
+  CR(a, QEMU_VIDEO_PRIVATE_DATA, GraphicsOutput, QEMU_VIDEO_PRIVATE_DATA_SIGNATURE)
+
+
+//
+// Global Variables
+//
+extern UINT8                                      AttributeController[];
+extern UINT8                                      GraphicsController[];
+extern UINT8                                      Crtc_640_480_256_60[];
+extern UINT16                                     Seq_640_480_256_60[];
+extern UINT8                                      Crtc_800_600_256_60[];
+extern UINT16                                     Seq_800_600_256_60[];
+extern UINT8                                      Crtc_1024_768_256_60[];
+extern UINT16                                     Seq_1024_768_256_60[];
+extern QEMU_VIDEO_CIRRUS_MODES                    QemuVideoCirrusModes[];
+extern QEMU_VIDEO_BOCHS_MODES                     QemuVideoBochsModes[];
+extern EFI_DRIVER_BINDING_PROTOCOL                gQemuVideoDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL                gQemuVideoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL               gQemuVideoComponentName2;
+extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL  gQemuVideoDriverSupportedEfiVersion;
+
+//
+// Io Registers defined by VGA
+//
+#define CRTC_ADDRESS_REGISTER   0x3d4
+#define CRTC_DATA_REGISTER      0x3d5
+#define SEQ_ADDRESS_REGISTER    0x3c4
+#define SEQ_DATA_REGISTER       0x3c5
+#define GRAPH_ADDRESS_REGISTER  0x3ce
+#define GRAPH_DATA_REGISTER     0x3cf
+#define ATT_ADDRESS_REGISTER    0x3c0
+#define MISC_OUTPUT_REGISTER    0x3c2
+#define INPUT_STATUS_1_REGISTER 0x3da
+#define DAC_PIXEL_MASK_REGISTER 0x3c6
+#define PALETTE_INDEX_REGISTER  0x3c8
+#define PALETTE_DATA_REGISTER   0x3c9
+
+#define VBE_DISPI_IOPORT_INDEX           0x01CE
+#define VBE_DISPI_IOPORT_DATA            0x01D0
+
+#define VBE_DISPI_INDEX_ID               0x0
+#define VBE_DISPI_INDEX_XRES             0x1
+#define VBE_DISPI_INDEX_YRES             0x2
+#define VBE_DISPI_INDEX_BPP              0x3
+#define VBE_DISPI_INDEX_ENABLE           0x4
+#define VBE_DISPI_INDEX_BANK             0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
+#define VBE_DISPI_INDEX_X_OFFSET         0x8
+#define VBE_DISPI_INDEX_Y_OFFSET         0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0                    0xB0C0
+#define VBE_DISPI_ID1                    0xB0C1
+#define VBE_DISPI_ID2                    0xB0C2
+#define VBE_DISPI_ID3                    0xB0C3
+#define VBE_DISPI_ID4                    0xB0C4
+#define VBE_DISPI_ID5                    0xB0C5
+
+#define VBE_DISPI_DISABLED               0x00
+#define VBE_DISPI_ENABLED                0x01
+#define VBE_DISPI_GETCAPS                0x02
+#define VBE_DISPI_8BIT_DAC               0x20
+#define VBE_DISPI_LFB_ENABLED            0x40
+#define VBE_DISPI_NOCLEARMEM             0x80
+
+//
+// Graphics Output Hardware abstraction internal worker functions
+//
+EFI_STATUS
+QemuVideoGraphicsOutputConstructor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  );
+
+EFI_STATUS
+QemuVideoGraphicsOutputDestructor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  );
+
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
+//
+/**
+  TODO: Add function description
+
+  @param  This TODO: add argument description
+  @param  Controller TODO: add argument description
+  @param  RemainingDevicePath TODO: add argument description
+
+  TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  TODO: Add function description
+
+  @param  This TODO: add argument description
+  @param  Controller TODO: add argument description
+  @param  RemainingDevicePath TODO: add argument description
+
+  TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  TODO: Add function description
+
+  @param  This TODO: add argument description
+  @param  Controller TODO: add argument description
+  @param  NumberOfChildren TODO: add argument description
+  @param  ChildHandleBuffer TODO: add argument description
+
+  TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer
+  );
+
+//
+// EFI Component Name Functions
+//
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+
+//
+// Local Function Prototypes
+//
+VOID
+InitializeCirrusGraphicsMode (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  QEMU_VIDEO_CIRRUS_MODES  *ModeData
+  );
+
+VOID
+InitializeBochsGraphicsMode (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  QEMU_VIDEO_BOCHS_MODES   *ModeData
+  );
+
+VOID
+SetPaletteColor (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Index,
+  UINT8                           Red,
+  UINT8                           Green,
+  UINT8                           Blue
+  );
+
+VOID
+SetDefaultPalette (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  );
+
+VOID
+DrawLogo (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           ScreenWidth,
+  UINTN                           ScreenHeight
+  );
+
+VOID
+outb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address,
+  UINT8                           Data
+  );
+
+VOID
+outw (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address,
+  UINT16                          Data
+  );
+
+UINT8
+inb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address
+  );
+
+UINT16
+inw (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                           Address
+  );
+
+VOID
+BochsWrite (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINT16                   Reg,
+  UINT16                   Data
+  );
+
+UINT16
+BochsRead (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINT16                   Reg
+  );
+
+VOID
+VgaOutb (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  UINTN                    Reg,
+  UINT8                    Data
+  );
+
+EFI_STATUS
+QemuVideoCirrusModeSetup (
+  QEMU_VIDEO_PRIVATE_DATA  *Private
+  );
+
+EFI_STATUS
+QemuVideoBochsModeSetup (
+  QEMU_VIDEO_PRIVATE_DATA  *Private,
+  BOOLEAN                  IsQxl
+  );
+
+VOID
+InstallVbeShim (
+  IN CONST CHAR16         *CardName,
+  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+  );
+#endif

+ 74 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf

@@ -0,0 +1,74 @@
+## @file
+#  This driver is a sample implementation of the Graphics Output Protocol for
+#  the QEMU (Cirrus Logic 5446) video controller.
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = QemuVideoDxe
+  FILE_GUID                      = e3752948-b9a1-4770-90c4-df41c38986be
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializeQemuVideo
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+#  DRIVER_BINDING                =  gQemuVideoDriverBinding
+#  COMPONENT_NAME                =  gQemuVideoComponentName
+#
+
+[Sources.common]
+  ComponentName.c
+  Driver.c
+  DriverSupportedEfiVersion.c
+  Gop.c
+  Initialize.c
+  Simics.h
+
+[Sources.Ia32, Sources.X64]
+  VbeShim.c
+  VbeShim.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OptionRomPkg/OptionRomPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  FrameBufferBltLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  PcdLib
+  PciLib
+  PrintLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  S3BootScriptLib
+
+[Protocols]
+  gEfiDriverSupportedEfiVersionProtocolGuid     # PROTOCOL ALWAYS_PRODUCED
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
+  gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
+  gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
+  gEfiDxeSmmReadyToLockProtocolGuid
+
+[Pcd]
+  gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask

+ 279 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm

@@ -0,0 +1,279 @@
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32, on the stdvga and QXL video
+; cards of QEMU.
+;
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+; enable this macro for debug messages
+;%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+  push       si
+  mov        si, %1
+  call       PrintStringSi
+  pop        si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+TIMES 256 nop
+
+
+Handler:
+  cmp        ax, 0x4f00
+  je         GetInfo
+  cmp        ax, 0x4f01
+  je         GetModeInfo
+  cmp        ax, 0x4f02
+  je         SetMode
+  cmp        ax, 0x4f03
+  je         GetMode
+  cmp        ax, 0x4f10
+  je         GetPmCapabilities
+  cmp        ax, 0x4f15
+  je         ReadEdid
+  cmp        ah, 0x00
+  je         SetModeLegacy
+  DebugLog   StrUnkownFunction
+Hang:
+  jmp        Hang
+
+
+GetInfo:
+  push       es
+  push       di
+  push       ds
+  push       si
+  push       cx
+
+  DebugLog   StrEnterGetInfo
+
+  ; target (es:di) set on input
+  push       cs
+  pop        ds
+  mov        si, VbeInfo
+  ; source (ds:si) set now
+
+  mov        cx, 256
+  cld
+  rep movsb
+
+  pop        cx
+  pop        si
+  pop        ds
+  pop        di
+  pop        es
+  jmp        Success
+
+
+GetModeInfo:
+  push       es
+  push       di
+  push       ds
+  push       si
+  push       cx
+
+  DebugLog   StrEnterGetModeInfo
+
+  and        cx, ~0x4000 ; clear potentially set LFB bit in mode number
+  cmp        cx, 0x00f1
+  je         KnownMode1
+  DebugLog   StrUnkownMode
+  jmp        Hang
+KnownMode1:
+  ; target (es:di) set on input
+  push       cs
+  pop        ds
+  mov        si, VbeModeInfo
+  ; source (ds:si) set now
+
+  mov        cx, 256
+  cld
+  rep movsb
+
+  pop        cx
+  pop        si
+  pop        ds
+  pop        di
+  pop        es
+  jmp        Success
+
+
+%define ATT_ADDRESS_REGISTER   0x03c0
+%define VBE_DISPI_IOPORT_INDEX 0x01ce
+%define VBE_DISPI_IOPORT_DATA  0x01d0
+
+%define VBE_DISPI_INDEX_XRES        0x1
+%define VBE_DISPI_INDEX_YRES        0x2
+%define VBE_DISPI_INDEX_BPP         0x3
+%define VBE_DISPI_INDEX_ENABLE      0x4
+%define VBE_DISPI_INDEX_BANK        0x5
+%define VBE_DISPI_INDEX_VIRT_WIDTH  0x6
+%define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+%define VBE_DISPI_INDEX_X_OFFSET    0x8
+%define VBE_DISPI_INDEX_Y_OFFSET    0x9
+
+%define VBE_DISPI_ENABLED     0x01
+%define VBE_DISPI_LFB_ENABLED 0x40
+
+%macro BochsWrite 2
+  push       dx
+  push       ax
+
+  mov        dx, VBE_DISPI_IOPORT_INDEX
+  mov        ax, %1
+  out        dx, ax
+
+  mov        dx, VBE_DISPI_IOPORT_DATA
+  mov        ax, %2
+  out        dx, ax
+
+  pop        ax
+  pop        dx
+%endmacro
+
+SetMode:
+  push       dx
+  push       ax
+
+  DebugLog   StrEnterSetMode
+
+  cmp        bx, 0x40f1
+  je         KnownMode2
+  DebugLog   StrUnkownMode
+  jmp        Hang
+KnownMode2:
+
+  ; unblank
+  mov        dx, ATT_ADDRESS_REGISTER
+  mov        al, 0x20
+  out        dx, al
+
+  BochsWrite VBE_DISPI_INDEX_ENABLE,        0
+  BochsWrite VBE_DISPI_INDEX_BANK,          0
+  BochsWrite VBE_DISPI_INDEX_X_OFFSET,      0
+  BochsWrite VBE_DISPI_INDEX_Y_OFFSET,      0
+  BochsWrite VBE_DISPI_INDEX_BPP,          32
+  BochsWrite VBE_DISPI_INDEX_XRES,       1024
+  BochsWrite VBE_DISPI_INDEX_VIRT_WIDTH, 1024
+  BochsWrite VBE_DISPI_INDEX_YRES,        768
+  BochsWrite VBE_DISPI_INDEX_VIRT_HEIGHT, 768
+  BochsWrite VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
+
+  pop        ax
+  pop        dx
+  jmp        Success
+
+
+GetMode:
+  DebugLog   StrEnterGetMode
+  mov        bx, 0x40f1
+  jmp        Success
+
+
+GetPmCapabilities:
+  DebugLog   StrGetPmCapabilities
+  jmp        Unsupported
+
+
+ReadEdid:
+  DebugLog   StrReadEdid
+  jmp        Unsupported
+
+
+SetModeLegacy:
+  DebugLog   StrEnterSetModeLegacy
+
+  cmp        al, 0x03
+  je         KnownMode3
+  cmp        al, 0x12
+  je         KnownMode4
+  DebugLog   StrUnkownMode
+  jmp        Hang
+KnownMode3:
+  mov        al, 0x30
+  jmp        SetModeLegacyDone
+KnownMode4:
+  mov        al, 0x20
+SetModeLegacyDone:
+  DebugLog   StrExitSuccess
+  iret
+
+
+Success:
+  DebugLog   StrExitSuccess
+  mov        ax, 0x004f
+  iret
+
+
+Unsupported:
+  DebugLog   StrExitUnsupported
+  mov        ax, 0x014f
+  iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+  pusha
+  push       ds ; save original
+  push       cs
+  pop        ds
+  mov        dx, 0x0402
+PrintStringSiLoop:
+  lodsb
+  cmp        al, 0
+  je         PrintStringSiDone
+  out        dx, al
+  jmp        PrintStringSiLoop
+PrintStringSiDone:
+  pop        ds ; restore original
+  popa
+  ret
+
+
+StrExitSuccess:
+  db 'Exit', 0x0a, 0
+
+StrExitUnsupported:
+  db 'Unsupported', 0x0a, 0
+
+StrUnkownFunction:
+  db 'Unknown Function', 0x0a, 0
+
+StrEnterGetInfo:
+  db 'GetInfo', 0x0a, 0
+
+StrEnterGetModeInfo:
+  db 'GetModeInfo', 0x0a, 0
+
+StrEnterGetMode:
+  db 'GetMode', 0x0a, 0
+
+StrEnterSetMode:
+  db 'SetMode', 0x0a, 0
+
+StrEnterSetModeLegacy:
+  db 'SetModeLegacy', 0x0a, 0
+
+StrUnkownMode:
+  db 'Unkown Mode', 0x0a, 0
+
+StrGetPmCapabilities:
+  db 'GetPmCapabilities', 0x0a, 0
+
+StrReadEdid:
+  db 'ReadEdid', 0x0a, 0
+%endif

+ 302 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c

@@ -0,0 +1,302 @@
+/** @file
+  Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+  Windows 2008 R2 SP1 UEFI guest.
+
+  The handler is never meant to be directly executed by a VCPU; it's there for
+  the internal real mode emulator of Windows 2008 R2 SP1.
+
+  The code is based on Ralf Brown's Interrupt List:
+  <http://www.cs.cmu.edu/~ralf/files.html>
+  <http://www.ctyme.com/rbrown.htm>
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+#include <SimicsPlatforms.h>
+
+#include "Simics.h"
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+  UINT16 Offset;
+  UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "OVMF Int10h (fake)";
+
+/**
+  Install the VBE Info and VBE Mode Info structures, and the VBE service
+  handler routine in the C segment. Point the real-mode Int10h interrupt vector
+  to the handler. The only advertised mode is 1024x768x32.
+
+  @param[in] CardName         Name of the video card to be exposed in the
+                              Product Name field of the VBE Info structure. The
+                              parameter must originate from a
+                              QEMU_VIDEO_CARD.Name field.
+  @param[in] FrameBufferBase  Guest-physical base address of the video card's
+                              frame buffer.
+**/
+VOID
+InstallVbeShim (
+  IN CONST CHAR16         *CardName,
+  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+  )
+{
+  EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+  UINTN                Segment0Pages;
+  IVT_ENTRY            *Int0x10;
+  EFI_STATUS           Segment0AllocationStatus;
+  UINT16               HostBridgeDevId;
+  UINTN                SegmentCPages;
+  VBE_INFO             *VbeInfoFull;
+  VBE_INFO_BASE        *VbeInfo;
+  UINT8                *Ptr;
+  UINTN                Printed;
+  VBE_MODE_INFO        *VbeModeInfo;
+
+  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
+    DEBUG ((
+      DEBUG_WARN,
+      "%a: page 0 protected, not installing VBE shim\n",
+      __FUNCTION__
+      ));
+    DEBUG ((
+      DEBUG_WARN,
+      "%a: page 0 protection prevents Windows 7 from booting anyway\n",
+      __FUNCTION__
+      ));
+    return;
+  }
+
+  Segment0 = 0x00000;
+  SegmentC = 0xC0000;
+  SegmentF = 0xF0000;
+
+  //
+  // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+  // driver, hence the arch protocols have been installed previously. Among
+  // those, the CPU arch protocol has configured the IDT, so we can overwrite
+  // the IVT used in real mode.
+  //
+  // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+  //
+  Segment0Pages = 1;
+  Int0x10       = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+  Segment0AllocationStatus = gBS->AllocatePages (
+                                    AllocateAddress,
+                                    EfiBootServicesCode,
+                                    Segment0Pages,
+                                    &Segment0
+                                    );
+
+  if (EFI_ERROR (Segment0AllocationStatus)) {
+    EFI_PHYSICAL_ADDRESS Handler;
+
+    //
+    // Check if a video BIOS handler has been installed previously -- we
+    // shouldn't override a real video BIOS with our shim, nor our own shim if
+    // it's already present.
+    //
+    Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+    if (Handler >= SegmentC && Handler < SegmentF) {
+      DEBUG ((EFI_D_INFO, "%a: Video BIOS handler found at %04x:%04x\n",
+        __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+      return;
+    }
+
+    //
+    // Otherwise we'll overwrite the Int10h vector, even though we may not own
+    // the page at zero.
+    //
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: failed to allocate page at zero: %r\n",
+      __FUNCTION__,
+      Segment0AllocationStatus
+      ));
+  } else {
+    //
+    // We managed to allocate the page at zero. SVN r14218 guarantees that it
+    // is NUL-filled.
+    //
+    ASSERT (Int0x10->Segment == 0x0000);
+    ASSERT (Int0x10->Offset  == 0x0000);
+  }
+
+  HostBridgeDevId = PcdGet16(PcdSimicsX58HostBridgePciDevId);
+  switch (HostBridgeDevId) {
+    case INTEL_ICH10_DEVICE_ID:
+      break;
+    default:
+      DEBUG((
+            DEBUG_ERROR,
+            "%a: unknown host bridge device ID: 0x%04x\n",
+            __FUNCTION__,
+            HostBridgeDevId
+      ));
+      ASSERT (FALSE);
+
+      if (!EFI_ERROR(Segment0AllocationStatus)) {
+        gBS->FreePages(Segment0, Segment0Pages);
+      }
+      return;
+  }
+  //
+  // low nibble covers 0xC0000 to 0xC3FFF
+  // high nibble covers 0xC4000 to 0xC7FFF
+  // bit1 in each nibble is Write Enable
+  // bit0 in each nibble is Read Enable
+  //
+
+  //
+  // We never added memory space during PEI or DXE for the C segment, so we
+  // don't need to (and can't) allocate from there. Also, guest operating
+  // systems will see a hole in the UEFI memory map there.
+  //
+  SegmentCPages = 4;
+
+  ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+  CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
+
+  //
+  // Fill in the VBE INFO structure.
+  //
+  VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+  VbeInfo     = &VbeInfoFull->Base;
+  Ptr         = VbeInfoFull->Buffer;
+
+  CopyMem (VbeInfo->Signature, "VESA", 4);
+  VbeInfo->VesaVersion = 0x0300;
+
+  VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+  CopyMem (Ptr, "QEMU", 5);
+  Ptr += 5;
+
+  VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode
+
+  VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+  *(UINT16*)Ptr = 0x00f1; // mode number
+  Ptr += 2;
+  *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+  Ptr += 2;
+
+  VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+  VbeInfo->OemSoftwareVersion = 0x0000;
+
+  VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+  CopyMem (Ptr, "OVMF", 5);
+  Ptr += 5;
+
+  VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+  Printed = AsciiSPrint ((CHAR8 *)Ptr,
+              sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+              CardName);
+  Ptr += Printed + 1;
+
+  VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+  CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+  Ptr += sizeof mProductRevision;
+
+  ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+  ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+  //
+  // Fil in the VBE MODE INFO structure.
+  //
+  VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+
+  //
+  // bit0: mode supported by present hardware configuration
+  // bit1: optional information available (must be =1 for VBE v1.2+)
+  // bit3: set if color, clear if monochrome
+  // bit4: set if graphics mode, clear if text mode
+  // bit5: mode is not VGA-compatible
+  // bit7: linear framebuffer mode supported
+  //
+  VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0;
+
+  //
+  // bit0: exists
+  // bit1: bit1: readable
+  // bit2: writeable
+  //
+  VbeModeInfo->WindowAAttr              = BIT2 | BIT1 | BIT0;
+
+  VbeModeInfo->WindowBAttr              = 0x00;
+  VbeModeInfo->WindowGranularityKB      = 0x0040;
+  VbeModeInfo->WindowSizeKB             = 0x0040;
+  VbeModeInfo->WindowAStartSegment      = 0xA000;
+  VbeModeInfo->WindowBStartSegment      = 0x0000;
+  VbeModeInfo->WindowPositioningAddress = 0x0000;
+  VbeModeInfo->BytesPerScanLine         = 1024 * 4;
+
+  VbeModeInfo->Width                = 1024;
+  VbeModeInfo->Height               = 768;
+  VbeModeInfo->CharCellWidth        = 8;
+  VbeModeInfo->CharCellHeight       = 16;
+  VbeModeInfo->NumPlanes            = 1;
+  VbeModeInfo->BitsPerPixel         = 32;
+  VbeModeInfo->NumBanks             = 1;
+  VbeModeInfo->MemoryModel          = 6; // direct color
+  VbeModeInfo->BankSizeKB           = 0;
+  VbeModeInfo->NumImagePagesLessOne = 0;
+  VbeModeInfo->Vbe3                 = 0x01;
+
+  VbeModeInfo->RedMaskSize      = 8;
+  VbeModeInfo->RedMaskPos       = 16;
+  VbeModeInfo->GreenMaskSize    = 8;
+  VbeModeInfo->GreenMaskPos     = 8;
+  VbeModeInfo->BlueMaskSize     = 8;
+  VbeModeInfo->BlueMaskPos      = 0;
+  VbeModeInfo->ReservedMaskSize = 8;
+  VbeModeInfo->ReservedMaskPos  = 24;
+
+  //
+  // bit1: Bytes in reserved field may be used by application
+  //
+  VbeModeInfo->DirectColorModeInfo = BIT1;
+
+  VbeModeInfo->LfbAddress       = (UINT32)FrameBufferBase;
+  VbeModeInfo->OffScreenAddress = 0;
+  VbeModeInfo->OffScreenSizeKB  = 0;
+
+  VbeModeInfo->BytesPerScanLineLinear = 1024 * 4;
+  VbeModeInfo->NumImagesLessOneBanked = 0;
+  VbeModeInfo->NumImagesLessOneLinear = 0;
+  VbeModeInfo->RedMaskSizeLinear      = 8;
+  VbeModeInfo->RedMaskPosLinear       = 16;
+  VbeModeInfo->GreenMaskSizeLinear    = 8;
+  VbeModeInfo->GreenMaskPosLinear     = 8;
+  VbeModeInfo->BlueMaskSizeLinear     = 8;
+  VbeModeInfo->BlueMaskPosLinear      = 0;
+  VbeModeInfo->ReservedMaskSizeLinear = 8;
+  VbeModeInfo->ReservedMaskPosLinear  = 24;
+  VbeModeInfo->MaxPixelClockHz        = 0;
+
+  ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved);
+
+  //
+  // Clear Write Enable (bit1), keep Read Enable (bit0) set
+  //
+
+  //
+  // Second, point the Int10h vector at the shim.
+  //
+  Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+  Int0x10->Offset  = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+  DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__));
+}

+ 701 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h

@@ -0,0 +1,701 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 mVbeShim[] = {
+  /* 00000000 nop                            */  0x90,
+  /* 00000001 nop                            */  0x90,
+  /* 00000002 nop                            */  0x90,
+  /* 00000003 nop                            */  0x90,
+  /* 00000004 nop                            */  0x90,
+  /* 00000005 nop                            */  0x90,
+  /* 00000006 nop                            */  0x90,
+  /* 00000007 nop                            */  0x90,
+  /* 00000008 nop                            */  0x90,
+  /* 00000009 nop                            */  0x90,
+  /* 0000000A nop                            */  0x90,
+  /* 0000000B nop                            */  0x90,
+  /* 0000000C nop                            */  0x90,
+  /* 0000000D nop                            */  0x90,
+  /* 0000000E nop                            */  0x90,
+  /* 0000000F nop                            */  0x90,
+  /* 00000010 nop                            */  0x90,
+  /* 00000011 nop                            */  0x90,
+  /* 00000012 nop                            */  0x90,
+  /* 00000013 nop                            */  0x90,
+  /* 00000014 nop                            */  0x90,
+  /* 00000015 nop                            */  0x90,
+  /* 00000016 nop                            */  0x90,
+  /* 00000017 nop                            */  0x90,
+  /* 00000018 nop                            */  0x90,
+  /* 00000019 nop                            */  0x90,
+  /* 0000001A nop                            */  0x90,
+  /* 0000001B nop                            */  0x90,
+  /* 0000001C nop                            */  0x90,
+  /* 0000001D nop                            */  0x90,
+  /* 0000001E nop                            */  0x90,
+  /* 0000001F nop                            */  0x90,
+  /* 00000020 nop                            */  0x90,
+  /* 00000021 nop                            */  0x90,
+  /* 00000022 nop                            */  0x90,
+  /* 00000023 nop                            */  0x90,
+  /* 00000024 nop                            */  0x90,
+  /* 00000025 nop                            */  0x90,
+  /* 00000026 nop                            */  0x90,
+  /* 00000027 nop                            */  0x90,
+  /* 00000028 nop                            */  0x90,
+  /* 00000029 nop                            */  0x90,
+  /* 0000002A nop                            */  0x90,
+  /* 0000002B nop                            */  0x90,
+  /* 0000002C nop                            */  0x90,
+  /* 0000002D nop                            */  0x90,
+  /* 0000002E nop                            */  0x90,
+  /* 0000002F nop                            */  0x90,
+  /* 00000030 nop                            */  0x90,
+  /* 00000031 nop                            */  0x90,
+  /* 00000032 nop                            */  0x90,
+  /* 00000033 nop                            */  0x90,
+  /* 00000034 nop                            */  0x90,
+  /* 00000035 nop                            */  0x90,
+  /* 00000036 nop                            */  0x90,
+  /* 00000037 nop                            */  0x90,
+  /* 00000038 nop                            */  0x90,
+  /* 00000039 nop                            */  0x90,
+  /* 0000003A nop                            */  0x90,
+  /* 0000003B nop                            */  0x90,
+  /* 0000003C nop                            */  0x90,
+  /* 0000003D nop                            */  0x90,
+  /* 0000003E nop                            */  0x90,
+  /* 0000003F nop                            */  0x90,
+  /* 00000040 nop                            */  0x90,
+  /* 00000041 nop                            */  0x90,
+  /* 00000042 nop                            */  0x90,
+  /* 00000043 nop                            */  0x90,
+  /* 00000044 nop                            */  0x90,
+  /* 00000045 nop                            */  0x90,
+  /* 00000046 nop                            */  0x90,
+  /* 00000047 nop                            */  0x90,
+  /* 00000048 nop                            */  0x90,
+  /* 00000049 nop                            */  0x90,
+  /* 0000004A nop                            */  0x90,
+  /* 0000004B nop                            */  0x90,
+  /* 0000004C nop                            */  0x90,
+  /* 0000004D nop                            */  0x90,
+  /* 0000004E nop                            */  0x90,
+  /* 0000004F nop                            */  0x90,
+  /* 00000050 nop                            */  0x90,
+  /* 00000051 nop                            */  0x90,
+  /* 00000052 nop                            */  0x90,
+  /* 00000053 nop                            */  0x90,
+  /* 00000054 nop                            */  0x90,
+  /* 00000055 nop                            */  0x90,
+  /* 00000056 nop                            */  0x90,
+  /* 00000057 nop                            */  0x90,
+  /* 00000058 nop                            */  0x90,
+  /* 00000059 nop                            */  0x90,
+  /* 0000005A nop                            */  0x90,
+  /* 0000005B nop                            */  0x90,
+  /* 0000005C nop                            */  0x90,
+  /* 0000005D nop                            */  0x90,
+  /* 0000005E nop                            */  0x90,
+  /* 0000005F nop                            */  0x90,
+  /* 00000060 nop                            */  0x90,
+  /* 00000061 nop                            */  0x90,
+  /* 00000062 nop                            */  0x90,
+  /* 00000063 nop                            */  0x90,
+  /* 00000064 nop                            */  0x90,
+  /* 00000065 nop                            */  0x90,
+  /* 00000066 nop                            */  0x90,
+  /* 00000067 nop                            */  0x90,
+  /* 00000068 nop                            */  0x90,
+  /* 00000069 nop                            */  0x90,
+  /* 0000006A nop                            */  0x90,
+  /* 0000006B nop                            */  0x90,
+  /* 0000006C nop                            */  0x90,
+  /* 0000006D nop                            */  0x90,
+  /* 0000006E nop                            */  0x90,
+  /* 0000006F nop                            */  0x90,
+  /* 00000070 nop                            */  0x90,
+  /* 00000071 nop                            */  0x90,
+  /* 00000072 nop                            */  0x90,
+  /* 00000073 nop                            */  0x90,
+  /* 00000074 nop                            */  0x90,
+  /* 00000075 nop                            */  0x90,
+  /* 00000076 nop                            */  0x90,
+  /* 00000077 nop                            */  0x90,
+  /* 00000078 nop                            */  0x90,
+  /* 00000079 nop                            */  0x90,
+  /* 0000007A nop                            */  0x90,
+  /* 0000007B nop                            */  0x90,
+  /* 0000007C nop                            */  0x90,
+  /* 0000007D nop                            */  0x90,
+  /* 0000007E nop                            */  0x90,
+  /* 0000007F nop                            */  0x90,
+  /* 00000080 nop                            */  0x90,
+  /* 00000081 nop                            */  0x90,
+  /* 00000082 nop                            */  0x90,
+  /* 00000083 nop                            */  0x90,
+  /* 00000084 nop                            */  0x90,
+  /* 00000085 nop                            */  0x90,
+  /* 00000086 nop                            */  0x90,
+  /* 00000087 nop                            */  0x90,
+  /* 00000088 nop                            */  0x90,
+  /* 00000089 nop                            */  0x90,
+  /* 0000008A nop                            */  0x90,
+  /* 0000008B nop                            */  0x90,
+  /* 0000008C nop                            */  0x90,
+  /* 0000008D nop                            */  0x90,
+  /* 0000008E nop                            */  0x90,
+  /* 0000008F nop                            */  0x90,
+  /* 00000090 nop                            */  0x90,
+  /* 00000091 nop                            */  0x90,
+  /* 00000092 nop                            */  0x90,
+  /* 00000093 nop                            */  0x90,
+  /* 00000094 nop                            */  0x90,
+  /* 00000095 nop                            */  0x90,
+  /* 00000096 nop                            */  0x90,
+  /* 00000097 nop                            */  0x90,
+  /* 00000098 nop                            */  0x90,
+  /* 00000099 nop                            */  0x90,
+  /* 0000009A nop                            */  0x90,
+  /* 0000009B nop                            */  0x90,
+  /* 0000009C nop                            */  0x90,
+  /* 0000009D nop                            */  0x90,
+  /* 0000009E nop                            */  0x90,
+  /* 0000009F nop                            */  0x90,
+  /* 000000A0 nop                            */  0x90,
+  /* 000000A1 nop                            */  0x90,
+  /* 000000A2 nop                            */  0x90,
+  /* 000000A3 nop                            */  0x90,
+  /* 000000A4 nop                            */  0x90,
+  /* 000000A5 nop                            */  0x90,
+  /* 000000A6 nop                            */  0x90,
+  /* 000000A7 nop                            */  0x90,
+  /* 000000A8 nop                            */  0x90,
+  /* 000000A9 nop                            */  0x90,
+  /* 000000AA nop                            */  0x90,
+  /* 000000AB nop                            */  0x90,
+  /* 000000AC nop                            */  0x90,
+  /* 000000AD nop                            */  0x90,
+  /* 000000AE nop                            */  0x90,
+  /* 000000AF nop                            */  0x90,
+  /* 000000B0 nop                            */  0x90,
+  /* 000000B1 nop                            */  0x90,
+  /* 000000B2 nop                            */  0x90,
+  /* 000000B3 nop                            */  0x90,
+  /* 000000B4 nop                            */  0x90,
+  /* 000000B5 nop                            */  0x90,
+  /* 000000B6 nop                            */  0x90,
+  /* 000000B7 nop                            */  0x90,
+  /* 000000B8 nop                            */  0x90,
+  /* 000000B9 nop                            */  0x90,
+  /* 000000BA nop                            */  0x90,
+  /* 000000BB nop                            */  0x90,
+  /* 000000BC nop                            */  0x90,
+  /* 000000BD nop                            */  0x90,
+  /* 000000BE nop                            */  0x90,
+  /* 000000BF nop                            */  0x90,
+  /* 000000C0 nop                            */  0x90,
+  /* 000000C1 nop                            */  0x90,
+  /* 000000C2 nop                            */  0x90,
+  /* 000000C3 nop                            */  0x90,
+  /* 000000C4 nop                            */  0x90,
+  /* 000000C5 nop                            */  0x90,
+  /* 000000C6 nop                            */  0x90,
+  /* 000000C7 nop                            */  0x90,
+  /* 000000C8 nop                            */  0x90,
+  /* 000000C9 nop                            */  0x90,
+  /* 000000CA nop                            */  0x90,
+  /* 000000CB nop                            */  0x90,
+  /* 000000CC nop                            */  0x90,
+  /* 000000CD nop                            */  0x90,
+  /* 000000CE nop                            */  0x90,
+  /* 000000CF nop                            */  0x90,
+  /* 000000D0 nop                            */  0x90,
+  /* 000000D1 nop                            */  0x90,
+  /* 000000D2 nop                            */  0x90,
+  /* 000000D3 nop                            */  0x90,
+  /* 000000D4 nop                            */  0x90,
+  /* 000000D5 nop                            */  0x90,
+  /* 000000D6 nop                            */  0x90,
+  /* 000000D7 nop                            */  0x90,
+  /* 000000D8 nop                            */  0x90,
+  /* 000000D9 nop                            */  0x90,
+  /* 000000DA nop                            */  0x90,
+  /* 000000DB nop                            */  0x90,
+  /* 000000DC nop                            */  0x90,
+  /* 000000DD nop                            */  0x90,
+  /* 000000DE nop                            */  0x90,
+  /* 000000DF nop                            */  0x90,
+  /* 000000E0 nop                            */  0x90,
+  /* 000000E1 nop                            */  0x90,
+  /* 000000E2 nop                            */  0x90,
+  /* 000000E3 nop                            */  0x90,
+  /* 000000E4 nop                            */  0x90,
+  /* 000000E5 nop                            */  0x90,
+  /* 000000E6 nop                            */  0x90,
+  /* 000000E7 nop                            */  0x90,
+  /* 000000E8 nop                            */  0x90,
+  /* 000000E9 nop                            */  0x90,
+  /* 000000EA nop                            */  0x90,
+  /* 000000EB nop                            */  0x90,
+  /* 000000EC nop                            */  0x90,
+  /* 000000ED nop                            */  0x90,
+  /* 000000EE nop                            */  0x90,
+  /* 000000EF nop                            */  0x90,
+  /* 000000F0 nop                            */  0x90,
+  /* 000000F1 nop                            */  0x90,
+  /* 000000F2 nop                            */  0x90,
+  /* 000000F3 nop                            */  0x90,
+  /* 000000F4 nop                            */  0x90,
+  /* 000000F5 nop                            */  0x90,
+  /* 000000F6 nop                            */  0x90,
+  /* 000000F7 nop                            */  0x90,
+  /* 000000F8 nop                            */  0x90,
+  /* 000000F9 nop                            */  0x90,
+  /* 000000FA nop                            */  0x90,
+  /* 000000FB nop                            */  0x90,
+  /* 000000FC nop                            */  0x90,
+  /* 000000FD nop                            */  0x90,
+  /* 000000FE nop                            */  0x90,
+  /* 000000FF nop                            */  0x90,
+  /* 00000100 nop                            */  0x90,
+  /* 00000101 nop                            */  0x90,
+  /* 00000102 nop                            */  0x90,
+  /* 00000103 nop                            */  0x90,
+  /* 00000104 nop                            */  0x90,
+  /* 00000105 nop                            */  0x90,
+  /* 00000106 nop                            */  0x90,
+  /* 00000107 nop                            */  0x90,
+  /* 00000108 nop                            */  0x90,
+  /* 00000109 nop                            */  0x90,
+  /* 0000010A nop                            */  0x90,
+  /* 0000010B nop                            */  0x90,
+  /* 0000010C nop                            */  0x90,
+  /* 0000010D nop                            */  0x90,
+  /* 0000010E nop                            */  0x90,
+  /* 0000010F nop                            */  0x90,
+  /* 00000110 nop                            */  0x90,
+  /* 00000111 nop                            */  0x90,
+  /* 00000112 nop                            */  0x90,
+  /* 00000113 nop                            */  0x90,
+  /* 00000114 nop                            */  0x90,
+  /* 00000115 nop                            */  0x90,
+  /* 00000116 nop                            */  0x90,
+  /* 00000117 nop                            */  0x90,
+  /* 00000118 nop                            */  0x90,
+  /* 00000119 nop                            */  0x90,
+  /* 0000011A nop                            */  0x90,
+  /* 0000011B nop                            */  0x90,
+  /* 0000011C nop                            */  0x90,
+  /* 0000011D nop                            */  0x90,
+  /* 0000011E nop                            */  0x90,
+  /* 0000011F nop                            */  0x90,
+  /* 00000120 nop                            */  0x90,
+  /* 00000121 nop                            */  0x90,
+  /* 00000122 nop                            */  0x90,
+  /* 00000123 nop                            */  0x90,
+  /* 00000124 nop                            */  0x90,
+  /* 00000125 nop                            */  0x90,
+  /* 00000126 nop                            */  0x90,
+  /* 00000127 nop                            */  0x90,
+  /* 00000128 nop                            */  0x90,
+  /* 00000129 nop                            */  0x90,
+  /* 0000012A nop                            */  0x90,
+  /* 0000012B nop                            */  0x90,
+  /* 0000012C nop                            */  0x90,
+  /* 0000012D nop                            */  0x90,
+  /* 0000012E nop                            */  0x90,
+  /* 0000012F nop                            */  0x90,
+  /* 00000130 nop                            */  0x90,
+  /* 00000131 nop                            */  0x90,
+  /* 00000132 nop                            */  0x90,
+  /* 00000133 nop                            */  0x90,
+  /* 00000134 nop                            */  0x90,
+  /* 00000135 nop                            */  0x90,
+  /* 00000136 nop                            */  0x90,
+  /* 00000137 nop                            */  0x90,
+  /* 00000138 nop                            */  0x90,
+  /* 00000139 nop                            */  0x90,
+  /* 0000013A nop                            */  0x90,
+  /* 0000013B nop                            */  0x90,
+  /* 0000013C nop                            */  0x90,
+  /* 0000013D nop                            */  0x90,
+  /* 0000013E nop                            */  0x90,
+  /* 0000013F nop                            */  0x90,
+  /* 00000140 nop                            */  0x90,
+  /* 00000141 nop                            */  0x90,
+  /* 00000142 nop                            */  0x90,
+  /* 00000143 nop                            */  0x90,
+  /* 00000144 nop                            */  0x90,
+  /* 00000145 nop                            */  0x90,
+  /* 00000146 nop                            */  0x90,
+  /* 00000147 nop                            */  0x90,
+  /* 00000148 nop                            */  0x90,
+  /* 00000149 nop                            */  0x90,
+  /* 0000014A nop                            */  0x90,
+  /* 0000014B nop                            */  0x90,
+  /* 0000014C nop                            */  0x90,
+  /* 0000014D nop                            */  0x90,
+  /* 0000014E nop                            */  0x90,
+  /* 0000014F nop                            */  0x90,
+  /* 00000150 nop                            */  0x90,
+  /* 00000151 nop                            */  0x90,
+  /* 00000152 nop                            */  0x90,
+  /* 00000153 nop                            */  0x90,
+  /* 00000154 nop                            */  0x90,
+  /* 00000155 nop                            */  0x90,
+  /* 00000156 nop                            */  0x90,
+  /* 00000157 nop                            */  0x90,
+  /* 00000158 nop                            */  0x90,
+  /* 00000159 nop                            */  0x90,
+  /* 0000015A nop                            */  0x90,
+  /* 0000015B nop                            */  0x90,
+  /* 0000015C nop                            */  0x90,
+  /* 0000015D nop                            */  0x90,
+  /* 0000015E nop                            */  0x90,
+  /* 0000015F nop                            */  0x90,
+  /* 00000160 nop                            */  0x90,
+  /* 00000161 nop                            */  0x90,
+  /* 00000162 nop                            */  0x90,
+  /* 00000163 nop                            */  0x90,
+  /* 00000164 nop                            */  0x90,
+  /* 00000165 nop                            */  0x90,
+  /* 00000166 nop                            */  0x90,
+  /* 00000167 nop                            */  0x90,
+  /* 00000168 nop                            */  0x90,
+  /* 00000169 nop                            */  0x90,
+  /* 0000016A nop                            */  0x90,
+  /* 0000016B nop                            */  0x90,
+  /* 0000016C nop                            */  0x90,
+  /* 0000016D nop                            */  0x90,
+  /* 0000016E nop                            */  0x90,
+  /* 0000016F nop                            */  0x90,
+  /* 00000170 nop                            */  0x90,
+  /* 00000171 nop                            */  0x90,
+  /* 00000172 nop                            */  0x90,
+  /* 00000173 nop                            */  0x90,
+  /* 00000174 nop                            */  0x90,
+  /* 00000175 nop                            */  0x90,
+  /* 00000176 nop                            */  0x90,
+  /* 00000177 nop                            */  0x90,
+  /* 00000178 nop                            */  0x90,
+  /* 00000179 nop                            */  0x90,
+  /* 0000017A nop                            */  0x90,
+  /* 0000017B nop                            */  0x90,
+  /* 0000017C nop                            */  0x90,
+  /* 0000017D nop                            */  0x90,
+  /* 0000017E nop                            */  0x90,
+  /* 0000017F nop                            */  0x90,
+  /* 00000180 nop                            */  0x90,
+  /* 00000181 nop                            */  0x90,
+  /* 00000182 nop                            */  0x90,
+  /* 00000183 nop                            */  0x90,
+  /* 00000184 nop                            */  0x90,
+  /* 00000185 nop                            */  0x90,
+  /* 00000186 nop                            */  0x90,
+  /* 00000187 nop                            */  0x90,
+  /* 00000188 nop                            */  0x90,
+  /* 00000189 nop                            */  0x90,
+  /* 0000018A nop                            */  0x90,
+  /* 0000018B nop                            */  0x90,
+  /* 0000018C nop                            */  0x90,
+  /* 0000018D nop                            */  0x90,
+  /* 0000018E nop                            */  0x90,
+  /* 0000018F nop                            */  0x90,
+  /* 00000190 nop                            */  0x90,
+  /* 00000191 nop                            */  0x90,
+  /* 00000192 nop                            */  0x90,
+  /* 00000193 nop                            */  0x90,
+  /* 00000194 nop                            */  0x90,
+  /* 00000195 nop                            */  0x90,
+  /* 00000196 nop                            */  0x90,
+  /* 00000197 nop                            */  0x90,
+  /* 00000198 nop                            */  0x90,
+  /* 00000199 nop                            */  0x90,
+  /* 0000019A nop                            */  0x90,
+  /* 0000019B nop                            */  0x90,
+  /* 0000019C nop                            */  0x90,
+  /* 0000019D nop                            */  0x90,
+  /* 0000019E nop                            */  0x90,
+  /* 0000019F nop                            */  0x90,
+  /* 000001A0 nop                            */  0x90,
+  /* 000001A1 nop                            */  0x90,
+  /* 000001A2 nop                            */  0x90,
+  /* 000001A3 nop                            */  0x90,
+  /* 000001A4 nop                            */  0x90,
+  /* 000001A5 nop                            */  0x90,
+  /* 000001A6 nop                            */  0x90,
+  /* 000001A7 nop                            */  0x90,
+  /* 000001A8 nop                            */  0x90,
+  /* 000001A9 nop                            */  0x90,
+  /* 000001AA nop                            */  0x90,
+  /* 000001AB nop                            */  0x90,
+  /* 000001AC nop                            */  0x90,
+  /* 000001AD nop                            */  0x90,
+  /* 000001AE nop                            */  0x90,
+  /* 000001AF nop                            */  0x90,
+  /* 000001B0 nop                            */  0x90,
+  /* 000001B1 nop                            */  0x90,
+  /* 000001B2 nop                            */  0x90,
+  /* 000001B3 nop                            */  0x90,
+  /* 000001B4 nop                            */  0x90,
+  /* 000001B5 nop                            */  0x90,
+  /* 000001B6 nop                            */  0x90,
+  /* 000001B7 nop                            */  0x90,
+  /* 000001B8 nop                            */  0x90,
+  /* 000001B9 nop                            */  0x90,
+  /* 000001BA nop                            */  0x90,
+  /* 000001BB nop                            */  0x90,
+  /* 000001BC nop                            */  0x90,
+  /* 000001BD nop                            */  0x90,
+  /* 000001BE nop                            */  0x90,
+  /* 000001BF nop                            */  0x90,
+  /* 000001C0 nop                            */  0x90,
+  /* 000001C1 nop                            */  0x90,
+  /* 000001C2 nop                            */  0x90,
+  /* 000001C3 nop                            */  0x90,
+  /* 000001C4 nop                            */  0x90,
+  /* 000001C5 nop                            */  0x90,
+  /* 000001C6 nop                            */  0x90,
+  /* 000001C7 nop                            */  0x90,
+  /* 000001C8 nop                            */  0x90,
+  /* 000001C9 nop                            */  0x90,
+  /* 000001CA nop                            */  0x90,
+  /* 000001CB nop                            */  0x90,
+  /* 000001CC nop                            */  0x90,
+  /* 000001CD nop                            */  0x90,
+  /* 000001CE nop                            */  0x90,
+  /* 000001CF nop                            */  0x90,
+  /* 000001D0 nop                            */  0x90,
+  /* 000001D1 nop                            */  0x90,
+  /* 000001D2 nop                            */  0x90,
+  /* 000001D3 nop                            */  0x90,
+  /* 000001D4 nop                            */  0x90,
+  /* 000001D5 nop                            */  0x90,
+  /* 000001D6 nop                            */  0x90,
+  /* 000001D7 nop                            */  0x90,
+  /* 000001D8 nop                            */  0x90,
+  /* 000001D9 nop                            */  0x90,
+  /* 000001DA nop                            */  0x90,
+  /* 000001DB nop                            */  0x90,
+  /* 000001DC nop                            */  0x90,
+  /* 000001DD nop                            */  0x90,
+  /* 000001DE nop                            */  0x90,
+  /* 000001DF nop                            */  0x90,
+  /* 000001E0 nop                            */  0x90,
+  /* 000001E1 nop                            */  0x90,
+  /* 000001E2 nop                            */  0x90,
+  /* 000001E3 nop                            */  0x90,
+  /* 000001E4 nop                            */  0x90,
+  /* 000001E5 nop                            */  0x90,
+  /* 000001E6 nop                            */  0x90,
+  /* 000001E7 nop                            */  0x90,
+  /* 000001E8 nop                            */  0x90,
+  /* 000001E9 nop                            */  0x90,
+  /* 000001EA nop                            */  0x90,
+  /* 000001EB nop                            */  0x90,
+  /* 000001EC nop                            */  0x90,
+  /* 000001ED nop                            */  0x90,
+  /* 000001EE nop                            */  0x90,
+  /* 000001EF nop                            */  0x90,
+  /* 000001F0 nop                            */  0x90,
+  /* 000001F1 nop                            */  0x90,
+  /* 000001F2 nop                            */  0x90,
+  /* 000001F3 nop                            */  0x90,
+  /* 000001F4 nop                            */  0x90,
+  /* 000001F5 nop                            */  0x90,
+  /* 000001F6 nop                            */  0x90,
+  /* 000001F7 nop                            */  0x90,
+  /* 000001F8 nop                            */  0x90,
+  /* 000001F9 nop                            */  0x90,
+  /* 000001FA nop                            */  0x90,
+  /* 000001FB nop                            */  0x90,
+  /* 000001FC nop                            */  0x90,
+  /* 000001FD nop                            */  0x90,
+  /* 000001FE nop                            */  0x90,
+  /* 000001FF nop                            */  0x90,
+  /* 00000200 cmp ax,0x4f00                  */  0x3D, 0x00, 0x4F,
+  /* 00000203 jz 0x22d                       */  0x74, 0x28,
+  /* 00000205 cmp ax,0x4f01                  */  0x3D, 0x01, 0x4F,
+  /* 00000208 jz 0x245                       */  0x74, 0x3B,
+  /* 0000020A cmp ax,0x4f02                  */  0x3D, 0x02, 0x4F,
+  /* 0000020D jz 0x269                       */  0x74, 0x5A,
+  /* 0000020F cmp ax,0x4f03                  */  0x3D, 0x03, 0x4F,
+  /* 00000212 jz word 0x331                  */  0x0F, 0x84, 0x1B, 0x01,
+  /* 00000216 cmp ax,0x4f10                  */  0x3D, 0x10, 0x4F,
+  /* 00000219 jz word 0x336                  */  0x0F, 0x84, 0x19, 0x01,
+  /* 0000021D cmp ax,0x4f15                  */  0x3D, 0x15, 0x4F,
+  /* 00000220 jz word 0x338                  */  0x0F, 0x84, 0x14, 0x01,
+  /* 00000224 cmp ah,0x0                     */  0x80, 0xFC, 0x00,
+  /* 00000227 jz word 0x33a                  */  0x0F, 0x84, 0x0F, 0x01,
+  /* 0000022B jmp short 0x22b                */  0xEB, 0xFE,
+  /* 0000022D push es                        */  0x06,
+  /* 0000022E push di                        */  0x57,
+  /* 0000022F push ds                        */  0x1E,
+  /* 00000230 push si                        */  0x56,
+  /* 00000231 push cx                        */  0x51,
+  /* 00000232 push cs                        */  0x0E,
+  /* 00000233 pop ds                         */  0x1F,
+  /* 00000234 mov si,0x0                     */  0xBE, 0x00, 0x00,
+  /* 00000237 mov cx,0x100                   */  0xB9, 0x00, 0x01,
+  /* 0000023A cld                            */  0xFC,
+  /* 0000023B rep movsb                      */  0xF3, 0xA4,
+  /* 0000023D pop cx                         */  0x59,
+  /* 0000023E pop si                         */  0x5E,
+  /* 0000023F pop ds                         */  0x1F,
+  /* 00000240 pop di                         */  0x5F,
+  /* 00000241 pop es                         */  0x07,
+  /* 00000242 jmp word 0x34c                 */  0xE9, 0x07, 0x01,
+  /* 00000245 push es                        */  0x06,
+  /* 00000246 push di                        */  0x57,
+  /* 00000247 push ds                        */  0x1E,
+  /* 00000248 push si                        */  0x56,
+  /* 00000249 push cx                        */  0x51,
+  /* 0000024A and cx,0xbfff                  */  0x81, 0xE1, 0xFF, 0xBF,
+  /* 0000024E cmp cx,0xf1                    */  0x81, 0xF9, 0xF1, 0x00,
+  /* 00000252 jz 0x256                       */  0x74, 0x02,
+  /* 00000254 jmp short 0x22b                */  0xEB, 0xD5,
+  /* 00000256 push cs                        */  0x0E,
+  /* 00000257 pop ds                         */  0x1F,
+  /* 00000258 mov si,0x100                   */  0xBE, 0x00, 0x01,
+  /* 0000025B mov cx,0x100                   */  0xB9, 0x00, 0x01,
+  /* 0000025E cld                            */  0xFC,
+  /* 0000025F rep movsb                      */  0xF3, 0xA4,
+  /* 00000261 pop cx                         */  0x59,
+  /* 00000262 pop si                         */  0x5E,
+  /* 00000263 pop ds                         */  0x1F,
+  /* 00000264 pop di                         */  0x5F,
+  /* 00000265 pop es                         */  0x07,
+  /* 00000266 jmp word 0x34c                 */  0xE9, 0xE3, 0x00,
+  /* 00000269 push dx                        */  0x52,
+  /* 0000026A push ax                        */  0x50,
+  /* 0000026B cmp bx,0x40f1                  */  0x81, 0xFB, 0xF1, 0x40,
+  /* 0000026F jz 0x273                       */  0x74, 0x02,
+  /* 00000271 jmp short 0x22b                */  0xEB, 0xB8,
+  /* 00000273 mov dx,0x3c0                   */  0xBA, 0xC0, 0x03,
+  /* 00000276 mov al,0x20                    */  0xB0, 0x20,
+  /* 00000278 out dx,al                      */  0xEE,
+  /* 00000279 push dx                        */  0x52,
+  /* 0000027A push ax                        */  0x50,
+  /* 0000027B mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 0000027E mov ax,0x4                     */  0xB8, 0x04, 0x00,
+  /* 00000281 out dx,ax                      */  0xEF,
+  /* 00000282 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 00000285 mov ax,0x0                     */  0xB8, 0x00, 0x00,
+  /* 00000288 out dx,ax                      */  0xEF,
+  /* 00000289 pop ax                         */  0x58,
+  /* 0000028A pop dx                         */  0x5A,
+  /* 0000028B push dx                        */  0x52,
+  /* 0000028C push ax                        */  0x50,
+  /* 0000028D mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 00000290 mov ax,0x5                     */  0xB8, 0x05, 0x00,
+  /* 00000293 out dx,ax                      */  0xEF,
+  /* 00000294 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 00000297 mov ax,0x0                     */  0xB8, 0x00, 0x00,
+  /* 0000029A out dx,ax                      */  0xEF,
+  /* 0000029B pop ax                         */  0x58,
+  /* 0000029C pop dx                         */  0x5A,
+  /* 0000029D push dx                        */  0x52,
+  /* 0000029E push ax                        */  0x50,
+  /* 0000029F mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002A2 mov ax,0x8                     */  0xB8, 0x08, 0x00,
+  /* 000002A5 out dx,ax                      */  0xEF,
+  /* 000002A6 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 000002A9 mov ax,0x0                     */  0xB8, 0x00, 0x00,
+  /* 000002AC out dx,ax                      */  0xEF,
+  /* 000002AD pop ax                         */  0x58,
+  /* 000002AE pop dx                         */  0x5A,
+  /* 000002AF push dx                        */  0x52,
+  /* 000002B0 push ax                        */  0x50,
+  /* 000002B1 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002B4 mov ax,0x9                     */  0xB8, 0x09, 0x00,
+  /* 000002B7 out dx,ax                      */  0xEF,
+  /* 000002B8 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 000002BB mov ax,0x0                     */  0xB8, 0x00, 0x00,
+  /* 000002BE out dx,ax                      */  0xEF,
+  /* 000002BF pop ax                         */  0x58,
+  /* 000002C0 pop dx                         */  0x5A,
+  /* 000002C1 push dx                        */  0x52,
+  /* 000002C2 push ax                        */  0x50,
+  /* 000002C3 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002C6 mov ax,0x3                     */  0xB8, 0x03, 0x00,
+  /* 000002C9 out dx,ax                      */  0xEF,
+  /* 000002CA mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 000002CD mov ax,0x20                    */  0xB8, 0x20, 0x00,
+  /* 000002D0 out dx,ax                      */  0xEF,
+  /* 000002D1 pop ax                         */  0x58,
+  /* 000002D2 pop dx                         */  0x5A,
+  /* 000002D3 push dx                        */  0x52,
+  /* 000002D4 push ax                        */  0x50,
+  /* 000002D5 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002D8 mov ax,0x1                     */  0xB8, 0x01, 0x00,
+  /* 000002DB out dx,ax                      */  0xEF,
+  /* 000002DC mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 000002DF mov ax,0x400                   */  0xB8, 0x00, 0x04,
+  /* 000002E2 out dx,ax                      */  0xEF,
+  /* 000002E3 pop ax                         */  0x58,
+  /* 000002E4 pop dx                         */  0x5A,
+  /* 000002E5 push dx                        */  0x52,
+  /* 000002E6 push ax                        */  0x50,
+  /* 000002E7 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002EA mov ax,0x6                     */  0xB8, 0x06, 0x00,
+  /* 000002ED out dx,ax                      */  0xEF,
+  /* 000002EE mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 000002F1 mov ax,0x400                   */  0xB8, 0x00, 0x04,
+  /* 000002F4 out dx,ax                      */  0xEF,
+  /* 000002F5 pop ax                         */  0x58,
+  /* 000002F6 pop dx                         */  0x5A,
+  /* 000002F7 push dx                        */  0x52,
+  /* 000002F8 push ax                        */  0x50,
+  /* 000002F9 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 000002FC mov ax,0x2                     */  0xB8, 0x02, 0x00,
+  /* 000002FF out dx,ax                      */  0xEF,
+  /* 00000300 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 00000303 mov ax,0x300                   */  0xB8, 0x00, 0x03,
+  /* 00000306 out dx,ax                      */  0xEF,
+  /* 00000307 pop ax                         */  0x58,
+  /* 00000308 pop dx                         */  0x5A,
+  /* 00000309 push dx                        */  0x52,
+  /* 0000030A push ax                        */  0x50,
+  /* 0000030B mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 0000030E mov ax,0x7                     */  0xB8, 0x07, 0x00,
+  /* 00000311 out dx,ax                      */  0xEF,
+  /* 00000312 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 00000315 mov ax,0x300                   */  0xB8, 0x00, 0x03,
+  /* 00000318 out dx,ax                      */  0xEF,
+  /* 00000319 pop ax                         */  0x58,
+  /* 0000031A pop dx                         */  0x5A,
+  /* 0000031B push dx                        */  0x52,
+  /* 0000031C push ax                        */  0x50,
+  /* 0000031D mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
+  /* 00000320 mov ax,0x4                     */  0xB8, 0x04, 0x00,
+  /* 00000323 out dx,ax                      */  0xEF,
+  /* 00000324 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
+  /* 00000327 mov ax,0x41                    */  0xB8, 0x41, 0x00,
+  /* 0000032A out dx,ax                      */  0xEF,
+  /* 0000032B pop ax                         */  0x58,
+  /* 0000032C pop dx                         */  0x5A,
+  /* 0000032D pop ax                         */  0x58,
+  /* 0000032E pop dx                         */  0x5A,
+  /* 0000032F jmp short 0x34c                */  0xEB, 0x1B,
+  /* 00000331 mov bx,0x40f1                  */  0xBB, 0xF1, 0x40,
+  /* 00000334 jmp short 0x34c                */  0xEB, 0x16,
+  /* 00000336 jmp short 0x350                */  0xEB, 0x18,
+  /* 00000338 jmp short 0x350                */  0xEB, 0x16,
+  /* 0000033A cmp al,0x3                     */  0x3C, 0x03,
+  /* 0000033C jz 0x345                       */  0x74, 0x07,
+  /* 0000033E cmp al,0x12                    */  0x3C, 0x12,
+  /* 00000340 jz 0x349                       */  0x74, 0x07,
+  /* 00000342 jmp word 0x22b                 */  0xE9, 0xE6, 0xFE,
+  /* 00000345 mov al,0x30                    */  0xB0, 0x30,
+  /* 00000347 jmp short 0x34b                */  0xEB, 0x02,
+  /* 00000349 mov al,0x20                    */  0xB0, 0x20,
+  /* 0000034B iretw                          */  0xCF,
+  /* 0000034C mov ax,0x4f                    */  0xB8, 0x4F, 0x00,
+  /* 0000034F iretw                          */  0xCF,
+  /* 00000350 mov ax,0x14f                   */  0xB8, 0x4F, 0x01,
+  /* 00000353 iretw                          */  0xCF,
+};
+#endif

+ 79 - 0
Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh

@@ -0,0 +1,79 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+  rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+      "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin -- "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^,  /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$,                              ,' \
+      -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+  printf '//\n'
+  printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+      "$(basename -- "$0")"
+  printf '//\n'
+  printf '#ifndef _VBE_SHIM_H_\n'
+  printf '#define _VBE_SHIM_H_\n'
+  printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
+  paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+  printf '};\n'
+  printf '#endif\n'
+} \
+| unix2dos >"$STEM".h