Browse Source

Platform/QuarkPlatformPkg: Import QuarkPlatformPkg from edk2

https://bugzilla.tianocore.org/show_bug.cgi?id=1374

Import QuarkPlatformPkg from edk2/master.

Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Michael Kubacki <michael.a.kubacki@intel.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Kelly Steele <kelly.steele@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Michael D Kinney 5 years ago
parent
commit
aa1cf38e84
100 changed files with 16315 additions and 0 deletions
  1. 42 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf
  2. 399 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl
  3. 159 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl
  4. 133 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl
  5. 73 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl
  6. 38 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/AD7298.asi
  7. 33 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/ADC108S102.asi
  8. 34 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/CAT24C08.asi
  9. 47 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/CY8C9540A.asi
  10. 89 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/GpioClient.asi
  11. 248 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi
  12. 34 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PCA9685.asi
  13. 90 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PCAL9555A.asi
  14. 195 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi
  15. 552 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi
  16. 127 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi
  17. 347 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl
  18. 49 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi
  19. 32 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi
  20. 23 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi
  21. 110 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi
  22. 45 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi
  23. 74 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc
  24. 29 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h
  25. 102 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h
  26. 76 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc
  27. 157 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc
  28. 68 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc
  29. 45 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h
  30. 75 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc
  31. 56 0
      Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h
  32. 1402 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c
  33. 316 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h
  34. 805 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c
  35. 120 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h
  36. 196 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf
  37. 207 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h
  38. 300 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c
  39. 77 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
  40. 44 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S
  41. 51 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm
  42. 57 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c
  43. 379 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c
  44. 70 0
      Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h
  45. 1011 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
  46. 167 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h
  47. 78 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
  48. 372 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
  49. 150 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h
  50. 113 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c
  51. 52 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h
  52. 74 0
      Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
  53. 47 0
      Platform/Intel/QuarkPlatformPkg/Application/ForceRecovery/ForceRecovery.c
  54. 34 0
      Platform/Intel/QuarkPlatformPkg/Application/ForceRecovery/ForceRecovery.inf
  55. 262 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
  56. 47 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf
  57. 330 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c
  58. 180 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h
  59. 83 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc
  60. 40 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf
  61. 60 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c
  62. 57 0
      Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareUpdateConfig/SystemFirmwareUpdateConfig.ini
  63. 23 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h
  64. 23 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h
  65. 24 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h
  66. 24 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h
  67. 23 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/MemoryConfigData.h
  68. 46 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h
  69. 23 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h
  70. 29 0
      Platform/Intel/QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h
  71. 266 0
      Platform/Intel/QuarkPlatformPkg/Include/Library/PlatformHelperLib.h
  72. 56 0
      Platform/Intel/QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h
  73. 24 0
      Platform/Intel/QuarkPlatformPkg/Include/Pcal9555.h
  74. 119 0
      Platform/Intel/QuarkPlatformPkg/Include/Platform.h
  75. 166 0
      Platform/Intel/QuarkPlatformPkg/Include/PlatformBoards.h
  76. 82 0
      Platform/Intel/QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h
  77. 23 0
      Platform/Intel/QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h
  78. 472 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
  79. 49 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h
  80. 83 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
  81. 275 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c
  82. 51 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h
  83. 70 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf
  84. 45 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf
  85. 337 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c
  86. 481 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c
  87. 159 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c
  88. 146 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformLeds.c
  89. 55 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h
  90. 114 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c
  91. 41 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf
  92. 125 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c
  93. 796 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S
  94. 685 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.asm
  95. 134 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Platform.inc
  96. 207 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLib.c
  97. 54 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLib.inf
  98. 18 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni
  99. 164 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c
  100. 41 0
      Platform/Intel/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf

+ 42 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/AcpiTables.inf

@@ -0,0 +1,42 @@
+## @file
+# Component description file for PlatformAcpiTable module.
+#
+# Build acpi table data required by system boot.
+# All .asi files tagged with "ToolCode="DUMMY"" in following
+# file list are device description and are included by top
+# level ASL file which will be dealed with by asl.exe application.
+#
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiTables
+  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]
+  Facs/Facs.aslc
+  Fadt/Fadt2.0.aslc
+  Hpet/Hpet.aslc
+  Mcfg/Mcfg.aslc
+  Dsdt/Platform.asl
+  CpuPm/CpuPm.asl
+  Cpu0Cst/Cpu0Cst.asl
+  Cpu0Ist/Cpu0Ist.asl
+  Cpu0Tst/Cpu0Tst.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec

+ 399 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Cst/Cpu0Cst.asl

@@ -0,0 +1,399 @@
+/** @file
+CPU C State control methods
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+    "Cpu0Cst.aml",
+    "SSDT",
+    0x01,
+    "SsgPmm",
+    "Cpu0Cst",
+    0x0011
+    )
+{
+    External(\_PR.CPU0, DeviceObj)
+    External (PDC0, IntObj)
+    External (CFGD, FieldUnitObj)
+
+    Scope(\_PR.CPU0)
+    {
+        Method (_CST, 0)
+        {
+            // If CMP is supported, and OSPM is not capable of independent C1, P, T state
+            // support for each processor for multi-processor configuration, we will just report
+            // C1 halt
+            //
+            // PDCx[4] = Indicates whether OSPM is not capable of independent C1, P, T state
+            // support for each processor for multi-processor configuration.
+            //
+            If(LAnd(And(CFGD,0x01000000), LNot(And(PDC0,0x10))))
+            {
+              Return(Package() {
+                1,
+                Package()
+                { // C1 halt
+                  ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+                  1,
+                  157,
+                  1000
+                }
+              })
+            }
+
+            //
+            // If MWAIT extensions is supported and OSPM is capable of performing
+            // native C state instructions for the C2/C3 in multi-processor configuration,
+            // we report every c state with MWAIT extensions.
+            //
+            // PDCx[9] = Indicates whether OSPM is capable of performing native C state instructions
+            // for the C2/C3 in multi-processor configuration
+            //
+            If(LAnd(And(CFGD, 0x200000), And(PDC0,0x200)))
+            {
+              //
+              // If C6 is supported, we report MWAIT C1,C2,C4,C6
+              //
+              If(And(CFGD,0x200))
+              {
+                Return( Package()
+                {
+                  4,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // MWAIT C2, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+                    2,
+                    20,
+                    500
+                  },
+                  Package()
+                  { // MWAIT C4, hardware coordinated with bus master avoidance enabled
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x30, 3)},
+                    3,
+                    100,
+                    100
+                  },
+                  Package()
+                  { // MWAIT C6, hardware coordinated with bus master avoidance enabled
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x50, 3)},
+                    3,
+                    140,
+                    10
+                  }
+                })
+              }
+              //
+              // If C4 is supported, we report MWAIT C1,C2,C4
+              //
+              If(And(CFGD,0x080))
+              {
+                Return( Package()
+                {
+                  3,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // MWAIT C2, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+                    2,
+                    20,
+                    500
+                  },
+                  Package()
+                  { // MWAIT C4, hardware coordinated with bus master avoidance enabled
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x30, 3)},
+                    3,
+                    100,
+                    100
+                  }
+                })
+              }
+              //
+              // If C2 is supported, we report MWAIT C1,C2
+              //
+              If(And(CFGD,0x020))
+              {
+                Return( Package()
+                {
+                  2,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // MWAIT C2, hardware coordinated with no bus master avoidance
+                    ResourceTemplate(){Register(FFixedHW, 1, 2, 0x10, 1)},
+                    2,
+                    20,
+                    500
+                  }
+                })
+              }
+              //
+              // Else we only report MWAIT C1.
+              //
+              Return(Package()
+              {
+                1,
+                Package()
+                { // MWAIT C1, hardware coordinated with no bus master avoidance
+                  ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+                  1,
+                  1,
+                  1000
+                }
+              })
+            }
+
+            // If OSPM is only capable of performing native C state instructions for
+            // the C1 in multi-processor configuration, we report C1 with MWAIT, other
+            // C states with IO method.
+            //
+            // PDCx[8] = Indicates whether OSPM is capable of performing native C state instructions
+            // for the C1 in multi-processor configuration
+            //
+            If(LAnd(And(CFGD, 0x200000), And(PDC0,0x100)))
+            {
+              //
+              // If C6 is supported, we report MWAIT C1, IO C2,C4,C6
+              //
+              If(And(CFGD,0x200))
+              {
+                Return( Package()
+                {
+                  4,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // IO C2 ("PMBALVL2" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                    2,
+                    20,
+                    500
+                    },
+                  Package()
+                  { // IO C4 ("PMBALVL4" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+                    3,
+                    100,
+                    100
+                  },
+                  Package()
+                  { // IO C6 ("PMBALVL6" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x364C564C41424D50)},
+                    3,
+                    140,
+                    10
+                  }
+                })
+              }
+              //
+              // If C4 is supported, we report MWAIT C1, IO C2,C4
+              //
+              If(And(CFGD,0x080))
+              {
+                Return( Package()
+                {
+                  3,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // IO C2 ("PMBALVL2" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                    2,
+                    20,
+                    500
+                    },
+                  Package()
+                  { // IO C4 ("PMBALVL4" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+                    3,
+                    100,
+                    100
+                  }
+                })
+              }
+              //
+              // If C2 is supported, we report MWAIT C1, IO C2
+              //
+              If(And(CFGD,0x020))
+              {
+                Return( Package()
+                {
+                  2,
+                  Package()
+                  { // MWAIT C1, hardware coordinated with no bus master avoidance
+                    ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+                    1,
+                    1,
+                    1000
+                  },
+                  Package()
+                  { // IO C2 ("PMBALVL2" will be updated at runtime)
+                    ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                    2,
+                    20,
+                    500
+                  }
+                })
+              }
+              //
+              // Else we only report MWAIT C1.
+              //
+              Return(Package()
+              {
+                1,
+                Package()
+                { // MWAIT C1, hardware coordinated with no bus master avoidance
+                  ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)},
+                  1,
+                  1,
+                  1000
+                }
+              })
+            }
+
+            //
+            // If MWAIT is not supported, we report all the c states with IO method
+            //
+
+            //
+            // If C6 is supported, we report C1 halt, IO C2,C4,C6
+            //
+            If(And(CFGD,0x200))
+            {
+              Return(Package()
+              {
+                4,
+                Package()
+                { // C1 Halt
+                  ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+                  1,
+                  1,
+                  1000
+                },
+                Package()
+                { // IO C2 ("PMBALVL2" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                  2,
+                  20,
+                  500
+                },
+                Package()
+                { // IO C4 ("PMBALVL4" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+                  3,
+                  100,
+                  100
+                },
+                Package()
+                { // IO C6 ("PMBALVL6" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x364C564C41424D50)},
+                  3,
+                  140,
+                  10
+                }
+              })
+            }
+            //
+            // If C4 is supported, we report C1 halt, IO C2,C4
+            //
+            If(And(CFGD,0x080))
+            {
+              Return(Package()
+              {
+                3,
+                Package()
+                { // C1 halt
+                  ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+                  1,
+                  1,
+                  1000
+                },
+                Package()
+                { // IO C2 ("PMBALVL2" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                  2,
+                  20,
+                  500
+                },
+                Package()
+                { // IO C4 ("PMBALVL4" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x344C564C41424D50)},
+                  3,
+                  100,
+                  100
+                }
+              })
+            }
+
+            //
+            // If C2 is supported, we report C1 halt, IO C2
+            //
+            If(And(CFGD,0x020))
+            {
+              Return(Package()
+              {
+                2,
+                Package()
+                { // C1 halt
+                  ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+                  1,
+                  1,
+                  1000
+                },
+                Package()
+                { // IO C2 ("PMBALVL2" will be updated at runtime)
+                  ResourceTemplate () {Register(SystemIO, 8, 0, 0x324C564C41424D50)},
+                  2,
+                  20,
+                  500
+                }
+              })
+            }
+            //
+            // Else we only report C1 halt.
+            //
+            Return(Package()
+            {
+              1,
+              Package()
+              { // C1 halt
+                ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+                1,
+                1,
+                1000
+              }
+            })
+        }
+    }
+}

+ 159 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Ist/Cpu0Ist.asl

@@ -0,0 +1,159 @@
+/** @file
+CPU EIST control methods
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+    "CPU0IST.aml",
+    "SSDT",
+    0x01,
+    "SsgPmm",
+    "Cpu0Ist",
+    0x0012
+    )
+{
+    External (PDC0, IntObj)
+    External (CFGD, FieldUnitObj)
+    External(\_PR.CPU0, DeviceObj)
+
+    Scope(\_PR.CPU0)
+    {
+        Method(_PPC,0)
+        {
+            Return(ZERO)   // Return All States Available.
+        }
+
+        Method(_PCT,0)
+        {
+            //
+            // If GV3 is supported and OSPM is capable of direct access to
+            // performance state MSR, we use MSR method
+            //
+            //
+            // PDCx[0] = Indicates whether OSPM is capable of direct access to
+            // performance state MSR.
+            //
+            If(LAnd(And(CFGD,0x0001), And(PDC0,0x0001)))
+            {
+                Return(Package()    // MSR Method
+                {
+                    ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+                    ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}
+                })
+
+            }
+
+            //
+            // Otherwise, we use smi method
+            //
+            Return(Package()    // SMI Method
+                {
+                  ResourceTemplate(){Register(SystemIO,16,0,0xB2)},
+                  ResourceTemplate(){Register(SystemIO, 8,0,0xB3)}
+                })
+        }
+
+        Method(_PSS,0)
+        {
+            //
+            // If OSPM is capable of direct access to performance state MSR,
+            // we report NPSS, otherwise, we report SPSS.
+            If (And(PDC0,0x0001))
+            {
+                Return(NPSS)
+            }
+
+            Return(SPSS)
+        }
+
+        Name(SPSS,Package()
+        {
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000}
+        })
+
+        Name(NPSS,Package()
+        {
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+            Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000}
+        })
+
+        Method(_PSD,0)
+        {
+          //
+          // If CMP is suppored, we report the dependency with two processors
+          //
+          If(And(CFGD,0x1000000))
+          {
+            //
+            // If OSPM is capable of hardware coordination of P-states, we report
+            // the dependency with hardware coordination.
+            //
+            // PDCx[11] = Indicates whether OSPM is capable of hardware coordination of P-states
+            //
+            If(And(PDC0,0x0800))
+            {
+              Return(Package(){
+                Package(){
+                  5,  // # entries.
+                  0,  // Revision.
+                  0,  // Domain #.
+                  0xFE,  // Coord Type- HW_ALL.
+                  2  // # processors.
+                }
+              })
+            }
+
+            //
+            // Otherwise, the dependency with OSPM coordination
+            //
+            Return(Package(){
+              Package(){
+                5,    // # entries.
+                0,    // Revision.
+                0,    // Domain #.
+                0xFC, // Coord Type- SW_ALL.
+                2     // # processors.
+              }
+            })
+          }
+
+          //
+          //  Otherwise, we report the dependency with one processor
+          //
+          Return(Package(){
+            Package(){
+              5,      // # entries.
+              0,      // Revision.
+              0,      // Domain #.
+              0xFC,   // Coord Type- SW_ALL.
+              1       // # processors.
+            }
+          })
+        }
+    }
+}

+ 133 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Cpu0Tst/Cpu0Tst.asl

@@ -0,0 +1,133 @@
+/** @file
+CPU T-state control methods
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+    "CPU0TST.aml",
+    "SSDT",
+    0x01,
+    "SsgPmm",
+    "Cpu0Tst",
+    0x0013
+    )
+{
+    External (PDC0, IntObj)
+    External (CFGD, FieldUnitObj)
+    External(\_PR.CPU0, DeviceObj)
+    External(_PSS)
+
+    Scope(\_PR.CPU0)
+    {
+        Method(_TPC,0)
+        {
+            Return(ZERO)   // Return All States Available.
+        }
+
+        Name(TPTC, ResourceTemplate()
+        {
+            Memory32Fixed(ReadOnly, 0, 0, FIX1) // IO APIC
+        })
+
+        //
+        // If OSPM is capable of direct access to on demand throttling MSR,
+        // we use MSR method;otherwise we use IO method.
+        //
+        //
+        // PDCx[2] = Indicates whether OSPM is capable of direct access to
+        // on demand throttling MSR.
+        //
+        Method(_PTC, 0)
+        {
+          If(And(PDC0, 0x0004))
+          {
+            Return(Package() // MSR Method
+            {
+              ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+              ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}
+            }
+            )
+          }
+          Return(Package() // IO Method
+          {
+            //
+            // PM IO base ("PMBALVL0" will be updated at runtime)
+            //
+            ResourceTemplate(){Register(SystemIO, 4, 1, 0x304C564C41424D50)},
+            ResourceTemplate(){Register(SystemIO, 4, 1, 0x304C564C41424D50)}
+          }
+          )
+        }
+
+        //
+        // _TSS returned package for IO Method
+        //
+        Name(TSSI, Package()
+        {
+          Package(){100, 1000, 0, 0x00, 0}
+        }
+        )
+        //
+        // _TSS returned package for MSR Method
+        //
+        Name(TSSM, Package()
+        {
+          Package(){100, 1000, 0, 0x00, 0}
+        }
+        )
+
+        Method(_TSS, 0)
+        {
+          //
+          // If OSPM is capable of direct access to on demand throttling MSR,
+          // we report TSSM;otherwise report TSSI.
+          //
+          If(And(PDC0, 0x0004))
+          {
+            Return(TSSM)
+          }
+          Return(TSSI)
+        }
+
+        Method(_TSD, 0)
+        {
+          //
+          // If CMP is suppored, we report the dependency with two processors
+          //
+          If(LAnd(And(CFGD, 0x1000000), LNot(And(PDC0, 4))))
+          {
+            Return(Package()
+            {
+              Package()
+              {
+                5,    // # entries.
+                0,    // Revision.
+                0,    // Domain #.
+                0xFD, // Coord Type- SW_ANY
+                2     // # processors.
+              }
+            }
+            )
+          }
+          //
+          // Otherwise, we report the dependency with one processor
+          //
+          Return(Package()
+          {
+            Package()
+            {
+              5,        // # entries.
+              0,        // Revision.
+              0,        // Domain #.
+              0xFC,     // Coord Type- SW_ALL
+              1         // # processors.
+            }
+          }
+          )
+        }
+    }
+}

+ 73 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/CpuPm/CpuPm.asl

@@ -0,0 +1,73 @@
+/** @file
+CPU power management control methods
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+    "CPUPM.aml",
+    "SSDT",
+    0x01,
+    "SsgPmm",
+    "CpuPm",
+    0x0010
+    )
+{
+    External(\_PR.CPU0, DeviceObj)
+    External(CFGD, FieldUnitObj)
+
+    Scope(\)
+    {
+        // Config DWord, modified during POST
+        // Bit definitions are the same as PPMFlags:
+        //     CFGD[0] = PPM_GV3     = GV3
+        //     CFGD[1] = PPM_TURBO   = Turbo Mode
+        //     CFGD[2] = PPM_SUPER_LFM = N/2 Ratio
+        //     CFGD[4] = PPM_C1      = C1 Capable, Enabled
+        //     CFGD[5] = PPM_C2      = C2 Capable, Enabled
+        //     CFGD[6] = PPM_C3      = C3 Capable, Enabled
+        //     CFGD[7] = PPM_C4      = C4 Capable, Enabled
+        //     CFGD[8] = PPM_C5      = C5/Deep C4 Capable, Enabled
+        //     CFGD[9] = PPM_C6      = C6 Capable, Enabled
+        //     CFGD[10] = PPM_C1E    = C1E Enabled
+        //     CFGD[11] = PPM_C2E    = C2E Enabled
+        //     CFGD[12] = PPM_C3E    = C3E Enabled
+        //     CFGD[13] = PPM_C4E    = C4E Enabled
+        //     CFGD[14] = PPM_HARD_C4E = Hard C4E Capable, Enabled
+        //     CFGD[16] = PPM_TM1    = Thermal Monitor 1
+        //     CFGD[17] = PPM_TM2    = Thermal Monitor 2
+        //     CFGD[19] = PPM_PHOT   = Bi-directional ProcHot
+        //     CFGD[21] = PPM_MWAIT_EXT = MWAIT extensions supported
+        //     CFGD[24] = PPM_CMP    = CMP supported, Enabled
+        //     CFGD[28] = PPM_TSTATE = CPU T states supported
+        //
+        // Name(CFGD, 0x80000000)
+        // External Defined in GNVS
+
+        Name(PDC0,0x80000000)   // CPU0 _PDC Flags.
+
+        // We load it in AcpiPlatform
+        //Name(SSDT,Package()
+        //{
+        //    "CPU0IST ", 0x80000000, 0x80000000,
+        //    "CPU1IST ", 0x80000000, 0x80000000,
+        //    "CPU0CST ", 0x80000000, 0x80000000,
+        //    "CPU1CST ", 0x80000000, 0x80000000,
+        //})
+    }
+    Scope(\_PR.CPU0)
+    {
+        Method(_PDC, 1)
+        {
+          //
+          // Store result of PDC.
+          //
+          CreateDWordField(Arg0,8,CAP0)   // Point to 3rd DWORD.
+          Store(CAP0,PDC0)                // Store It in PDC0.
+        }
+    }
+
+}

+ 38 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/AD7298.asi

@@ -0,0 +1,38 @@
+/** @file
+Analog devices AD7298 ADC.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(ADC1)
+{
+    Name(_HID, "INT3494") // Galileo Version 1 Low-Speed ADC.
+    Name(_CID, "INT3494")
+    Name(RBUF, ResourceTemplate()
+    {
+        // SPI0: mode 2, 4Mhz, 16-bit data length
+        SpiSerialBus (0x0000, PolarityLow, FourWireMode, 16, ControllerInitiated, 4000000, ClockPolarityHigh, ClockPhaseFirst, "\\_SB_.PCI0.SPI0",0x00, ResourceConsumer, ,)
+
+        // GPIO<0> is SPI0_CS_N
+        GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {QUARK_GPIO0_MAPPING}
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Galileo platform has this device.
+        // EFI_PLATFORM_TYPE enum value Galileo = 6.
+        //
+        If(LNotEqual(PTYP, 6))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 33 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/ADC108S102.asi

@@ -0,0 +1,33 @@
+/** @file
+TI ADC108S102 ADC.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(ADC2)
+{
+    Name(_HID, "INT3495") // GalileoGen2 Low-Speed ADC.
+    Name(_CID, "INT3495")
+    Name(RBUF, ResourceTemplate()
+    {
+        SPISerialBus(0x0000, PolarityLow, ThreeWireMode, 0x10, ControllerInitiated, 0x1E8480, ClockPolarityLow, ClockPhaseFirst, "\\_SB.PCI0.SPI0", 0x00, ResourceConsumer, ,)
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 34 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/CAT24C08.asi

@@ -0,0 +1,34 @@
+/** @file
+ONSEMI CAT24C08 I2C 8KB EEPROM.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(EEP2)
+{
+    Name(_HID, "INT3499") // ONSEMI CAT24C08 I2C 8KB EEPROM.
+    Name(_CID, "INT3499")
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x54, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 47 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/CY8C9540A.asi

@@ -0,0 +1,47 @@
+/** @file
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+CY8C9540A 40 Bit I/O Expander with EEPROM.
+
+**/
+
+Device(CY8C)
+{
+    Name(_HID, "INT3490") // Cypress CY8C9540A Io Expander Function.
+    Name(_CID, "INT3490")
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x20, ControllerInitiated, 100000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+        GpioInt (Level, ActiveLow, Exclusive, PullDefault, , "\\_SB.PCI0.GIP0.GPO", 0, ResourceConsumer, , ) {QUARK_GPIO5_MAPPING} /* GPIO<5> is INT_S0 */
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        CreateByteField(RBUF, 16, OB1)
+        if (LEqual (ALTS, 0))
+        {
+            Store(0x20, OB1)
+        }
+        Else
+        {
+            Store(0x21, OB1)
+        }
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Galileo platform has this device.
+        // EFI_PLATFORM_TYPE enum value Galileo = 6.
+        //
+        If(LNotEqual(PTYP, 6))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}
+

+ 89 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/GpioClient.asi

@@ -0,0 +1,89 @@
+/** @file
+Expose GPIO resources to usermode through client driver.
+
+Copyright (c) 2013-2019 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(GPOT)
+{
+    Name(_HID, "INT349A")
+    Name(_CID, "INT349A")
+    Method(_CRS, 0x0, Serialized)
+    {
+        Name(RBUF, ResourceTemplate()
+        {
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x1}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x2}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x3}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x4}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x5}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x6}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x7}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x8}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0x9}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xa}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xb}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xc}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xd}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xe}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.PCI0.GIP0.GPO_", 0, ResourceConsumer, , ) {0xf}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x2}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x3}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x4}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x5}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x6}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x7}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x8}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x9}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xa}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xb}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xc}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xd}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xe}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0xf}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x10}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x11}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x12}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x13}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x14}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x15}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x16}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x17}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x18}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x19}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1a}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1b}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1c}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1d}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1e}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x1f}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x20}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x21}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x22}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x23}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x24}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x25}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x26}
+            GpioIO(Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.CY8C", 0, ResourceConsumer, , ) {0x27}
+        })
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Galileo platform has this device.
+        // EFI_PLATFORM_TYPE enum value Galileo = 6.
+        //
+        If(LNotEqual(PTYP, 6))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 248 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/LpcDev.asi

@@ -0,0 +1,248 @@
+/** @file
+Legacy resource template
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef LPC_DEV_ASI
+#define LPC_DEV_ASI
+
+Device(RTC)
+{
+    Name(_HID,EISAID("PNP0B00"))
+    Name(BUF0,ResourceTemplate() {
+        IO(Decode16,0x70,0x70,0x01,0x04)
+        IO(Decode16,0x74,0x74,0x01,0x04)
+    })
+    Name(BUF1,ResourceTemplate() {
+        IO(Decode16,0x70,0x70,0x01,0x04)
+        IO(Decode16,0x74,0x74,0x01,0x04)
+        IRQNoFlags(){8}
+    })
+    Method(_CRS,0,Serialized)
+    {
+        If (HPEA)
+        {
+            return (BUF0)
+        }
+        Else
+        {
+            return (BUF1)
+        }
+    }
+}
+
+Device(PIC)
+{
+    Name(_HID,EISAID("PNP0000"))
+
+    Name(_CRS,ResourceTemplate() {
+        IO(Decode16,0x20,0x20,0x01,0x1E)        // length of 1Eh includes all aliases
+        IO(Decode16,0xA0,0xA0,0x01,0x1E)
+        IO(Decode16,0x4D0,0x4D0,0x01,0x02)
+    })
+}
+
+Device(TMR)
+{
+    Name(_HID,EISAID("PNP0100"))
+
+    Name(BUF0,ResourceTemplate() {
+        IO(Decode16,0x40,0x40,0x01,0x04)
+        IO(Decode16,0x50,0x50,0x01,0x04)        // alias
+    })
+    Name(BUF1,ResourceTemplate() {
+        IO(Decode16,0x40,0x40,0x01,0x04)
+        IO(Decode16,0x50,0x50,0x01,0x04)        // alias
+        IRQNoFlags(){0}
+    })
+    Method(_CRS,0,Serialized)
+    {
+        If (HPEA)
+        {
+            return (BUF0)
+        }
+        Else
+        {
+            return (BUF1)
+        }
+    }
+}
+
+Device(SPKR)
+{
+    Name(_HID,EISAID("PNP0800"))
+
+    Name(_CRS,ResourceTemplate() {
+        IO(Decode16,0x61,0x61,0x01,0x01)
+    })
+}
+
+Device(XTRA)    // all "PNP0C02" devices- pieces that don't fit anywhere else
+{
+    Name(_HID,EISAID("PNP0C02"))        // Generic motherboard devices
+
+    Name(CRS,
+        ResourceTemplate()
+        {
+            IO(Decode16,0x2E,0x2E,0x01,0x02)
+            IO(Decode16,0x4E,0x2E,0x01,0x02)
+            IO(Decode16,0x63,0x61,0x01,0x01)
+            IO(Decode16,0x65,0x61,0x01,0x01)
+            IO(Decode16,0x67,0x61,0x01,0x01)
+            IO(Decode16,0x80,0x80,0x01,0x01)
+            IO(Decode16,0x84,0x84,0x01,0x04)
+            IO(Decode16,0x88,0x88,0x01,0x01)
+            IO(Decode16,0x8c,0x8c,0x01,0x03)
+            IO(Decode16,0x92,0x92,0x01,0x01)
+
+            IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x10,
+              FIX1
+              )
+
+            IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x10,
+              FIX2
+              )
+
+            IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x40,
+              FIX3
+              )
+
+           IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x40,
+              FIX5
+              )
+
+            IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x40,
+              FIX6
+              )
+
+        }
+    )
+
+    Method (_CRS, 0, NotSerialized) {
+      CreateWordField (CRS, ^FIX1._MIN, MBR0)
+      Store(\P1BB, MBR0)
+      CreateWordField (CRS, ^FIX1._MAX, MBR1)
+      Store(\P1BB, MBR1)
+      CreateWordField (CRS, ^FIX2._MIN, MBR2)
+      Store(\PBAB, MBR2)
+      CreateWordField (CRS, ^FIX2._MAX, MBR3)
+      Store(\PBAB, MBR3)
+      CreateWordField (CRS, ^FIX3._MIN, MBR4)
+      Store(\GP0B, MBR4)
+      CreateWordField (CRS, ^FIX3._MAX, MBR5)
+      Store(\GP0B, MBR5)
+      CreateWordField (CRS, ^FIX5._MIN, MBR8)
+      Store(\SMBB, MBR8)
+      CreateWordField (CRS, ^FIX5._MAX, MBR9)
+      Store(\SMBB, MBR9)
+      CreateWordField (CRS, ^FIX6._MIN, MBRA)
+      Store(\WDTB, MBRA)
+      CreateWordField (CRS, ^FIX6._MAX, MBRB)
+      Store(\WDTB, MBRB)
+      return (CRS)
+    }
+}
+
+Device(LGIO)  // Legacy GPIO.
+{
+    Name(_HID, "INT3488")
+    Name(_CID, "INT3488")
+
+    Name(CRS,
+        ResourceTemplate()
+        {
+            IO(
+              Decode16,
+              0,
+              0,
+              0x01,
+              0x48,
+              FIX4
+              )
+        }
+    )
+
+    Method (_CRS, 0, NotSerialized) {
+      CreateWordField (CRS, ^FIX4._MIN, MBR6)
+      Store(\GPAB, MBR6)
+      CreateWordField (CRS, ^FIX4._MAX, MBR7)
+      Store(\GPAB, MBR7)
+      return (CRS)
+    }
+}
+
+Device(HPET)  // High Performance Event Timer
+{
+  Name(_HID,EISAID("PNP0103"))
+
+  Name(BUF0,ResourceTemplate()
+  {
+    IRQNoFlags() {0}
+    IRQNoFlags() {8}
+    Memory32Fixed(ReadOnly, 0, 0, FIX1)
+  })
+
+  Method(_STA,0)
+  {
+    // Show this Device only if the OS is WINXP or beyond.
+
+    If(LGreaterEqual(OSTP,WINDOWS_XP))
+    {
+      If(HPEA)
+      {
+        Return(0x000F)  // Enabled, do Display.
+      }
+    }
+    Else
+    {
+      // OS = WIN98, WINME, or WIN2000.
+
+      If(HPEA)
+      {
+        Return(0x000B)  // Enabled, don't Display.
+      }
+    }
+
+    Return(0x0000)      // Return Nothing.
+  }
+
+  Method(_CRS,0,Serialized)
+  {
+    CreateDWordField (BUF0, ^FIX1._BAS, MBR0)
+    Store(\HPTB, MBR0)
+    CreateDWordField (BUF0, ^FIX1._LEN, MBR1)
+    Store(\HPTS, MBR1)
+    Return(BUF0)
+  }
+}
+
+#endif

+ 34 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PCA9685.asi

@@ -0,0 +1,34 @@
+/** @file
+NXP PCA9685 i2c-accessible PWM/LED controller.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(PWM1)
+{
+    Name(_HID, "INT3492") // NXP PCA9685 i2c-accessible PWM/LED controller.
+    Name(_CID, "INT3492")
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x47, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 90 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PCAL9555A.asi

@@ -0,0 +1,90 @@
+/** @file
+NXP PCAL9555A i2c-accessible I/O expander.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device(NIO1)
+{
+    Name(_HID, "INT3491") // NXP PCAL9555A i2c-accessible I/O expander.
+    Name(_CID, "INT3491")
+    Name(_UID, 1)
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x25, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}
+
+Device(NIO2)
+{
+    Name(_HID, "INT3491") // NXP PCAL9555A i2c-accessible I/O expander.
+    Name(_CID, "INT3491")
+    Name(_UID, 2)
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x26, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}
+
+Device(NIO3)
+{
+    Name(_HID, "INT3491") // NXP PCAL9555A i2c-accessible I/O expander.
+    Name(_CID, "INT3491")
+    Name(_UID, 3)
+
+    Name(RBUF, ResourceTemplate()
+    {
+        I2CSerialBus(0x27, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer, , )
+        GpioInt (Level, ActiveLow, Exclusive, PullDefault, , "\\_SB.PCI0.GIP0.GPO", 0, ResourceConsumer, , ) {QUARK_GPIO1_MAPPING} /* GPIO<1> is EXP2_INT */
+    })
+    Method(_CRS, 0x0, NotSerialized)
+    {
+        Return(RBUF)
+    }
+    Method(_STA, 0x0, NotSerialized)
+    {
+        //
+        // Only Platform Type / Id 8 has this device.
+        //
+        If(LNotEqual(PTYP, 8))
+        {
+          return (0)
+        }
+        Return(0xf)
+    }
+}

+ 195 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciHostBridge.asi

@@ -0,0 +1,195 @@
+/** @file
+PCI Host Bridge Definitions
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+Name(PBRS, 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
+      0x001f,                // Max
+      0x0000,                // Translation
+      0x0020                 // Range Length = Max-Min+1
+   )
+
+   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
+   )
+
+   IO(                       //Consumed resource (CF8-CFF)
+      Decode16,
+      0x0cf8,
+      0xcf8,
+      1,
+      8
+   )
+
+   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 dos area(0->0xa0000)
+      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(              // Consumed-and-produced resource for pci memory mapped memory
+      ResourceProducer,      // bit 0 of general flags is 0
+      PosDecode,             // positive Decode
+      MinFixed,              // Range is fixed
+      MaxFixed,              // Range is fixed
+      Cacheable,
+      ReadWrite,
+      0x00000000,            // Granularity
+      0x00000000,            // Min (calculated dynamically)
+
+      0xfebfffff,            // Max = IO Apic base address - 1
+      0x00000000,            // Translation
+      0xfec00000,            // Range Length (calculated dynamically)
+      ,                      // Optional field left blank
+      ,                      // Optional field left blank
+      MEM1                   // Name declaration for this descriptor
+   )
+
+})          // end of CRES Buffer
+
+
+Method(_CRS, 0x0, NotSerialized)
+{
+    CreateDWordField(PBRS, \_SB.PCI0.MEM1._MIN, MMIN)
+    CreateDWordField(PBRS, \_SB.PCI0.MEM1._MAX, MMAX)
+    CreateDWordField(PBRS, \_SB.PCI0.MEM1._LEN, MLEN)
+
+    // HMBOUND is PCI memory base
+    And(MNRD(0x03, 0x08), 0xFFFFF000, MMIN)
+    Add(Subtract(MMAX, MMIN), 1, MLEN)
+
+    Return(PBRS)
+}
+
+// Message Nework Registers
+OperationRegion(MNR, PCI_Config, 0xD0, 0x10)
+Field(MNR, DWordAcc, NoLock, Preserve)
+{
+    MCR, 32,           // Message Control Register
+    MDR, 32            // Message Data Register
+}
+
+// Message Nework Read Method
+// Arg0 = Port
+// Arg1 = RegAddress
+// return 32 bit register value
+Method(MNRD, 2, Serialized)
+{
+    Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0)
+    Or(Local0, 0x100000F0, Local0)
+    Store(Local0, MCR)
+    Return(MDR)
+}
+
+// Message Nework Write Method
+// Arg0 = Port
+// Arg1 = RegAddress
+// Arg2 = 32 bit write value
+Method(MNWR, 3, Serialized)
+{
+    Store(Arg2, MDR)
+    Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0)
+    Or(Local0, 0x110000F0, Local0)
+    Store(Local0, MCR)
+}
+
+Method(_PRT, 0, NotSerialized)
+{
+  If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+  {
+    Return (
+      Package()
+      {
+        // Bus 0, Device 20 - IOSFAHB Bridge
+        Package() {0x0014ffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // INTA
+        Package() {0x0014ffff, 1, \_SB.PCI0.LPC.LNKB, 0}, // INTB
+        Package() {0x0014ffff, 2, \_SB.PCI0.LPC.LNKC, 0}, // INTC
+        Package() {0x0014ffff, 3, \_SB.PCI0.LPC.LNKD, 0}, // INTD
+
+        // Bus 0, Device 21 - IOSFAHB Bridge
+        Package() {0x0015ffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // INTA
+        Package() {0x0015ffff, 1, \_SB.PCI0.LPC.LNKB, 0}, // INTB
+        Package() {0x0015ffff, 2, \_SB.PCI0.LPC.LNKC, 0}, // INTC
+        Package() {0x0015ffff, 3, \_SB.PCI0.LPC.LNKD, 0}, // INTD
+
+        // Bus 0, Device 23 - PCIe port 0
+        Package() {0x0017ffff, 0, \_SB.PCI0.LPC.LNKE, 0}, // INTA
+        Package() {0x0017ffff, 1, \_SB.PCI0.LPC.LNKF, 0}, // INTB
+        Package() {0x0017ffff, 2, \_SB.PCI0.LPC.LNKG, 0}, // INTC
+        Package() {0x0017ffff, 3, \_SB.PCI0.LPC.LNKH, 0}, // INTD
+
+        // Bus 0, Device 31
+        Package() {0x001fffff, 0, \_SB.PCI0.LPC.LNKA, 0}, // LPC Bridge
+      }
+    )
+  }
+  else {
+    Return (
+      Package()
+      {
+        // Bus 0, Device 20 - IOSFAHB Bridge
+        Package() {0x0014ffff, 0, 0, 16}, // INTA
+        Package() {0x0014ffff, 1, 0, 17}, // INTB
+        Package() {0x0014ffff, 2, 0, 18}, // INTC
+        Package() {0x0014ffff, 3, 0, 19}, // INTD
+
+        // Bus 0, Device 21 - IOSFAHB Bridge
+        Package() {0x0015ffff, 0, 0, 16}, // INTA
+        Package() {0x0015ffff, 1, 0, 17}, // INTB
+        Package() {0x0015ffff, 2, 0, 18}, // INTC
+        Package() {0x0015ffff, 3, 0, 19}, // INTD
+
+        // Bus 0, Device 23 - PCIe port 0
+        Package() {0x0017ffff, 0, 0, 20}, // INTA
+        Package() {0x0017ffff, 1, 0, 21}, // INTB
+        Package() {0x0017ffff, 2, 0, 22}, // INTC
+        Package() {0x0017ffff, 3, 0, 23}, // INTD
+
+        // Bus 0, Device 31
+        Package() {0x001fffff, 0, 0, 16}, // LPC Bridge
+      }
+    )
+  }
+}

+ 552 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PciIrq.asi

@@ -0,0 +1,552 @@
+/** @file
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+// Interrupts can be DEB8=all except 13,8,6,2,1,0
+
+#ifndef PCIIRQ_ASI
+#define PCIIRQ_ASI
+
+OperationRegion(PRR0, PCI_Config, 0x60, 0x08)
+Field(PRR0, ANYACC, NOLOCK, PRESERVE)
+{
+    PIRA, 8,
+    PIRB, 8,
+    PIRC, 8,
+    PIRD, 8,
+    PIRE, 8,
+    PIRF, 8,
+    PIRG, 8,
+    PIRH, 8
+}
+
+Device(LNKA)            // PCI IRQ link A
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 1)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRA, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRA, 0x80, PIRA)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRA, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }
+                                                    // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRA,0x0F),IRQW)       // Save in buffer
+        Return(BUF0)                                // Return Buf0
+    }                                               // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRA)
+    }                                                  // End of _SRS Method
+}
+
+Device(LNKB)            // PCI IRQ link B
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 2)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRB, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRB, 0x80,PIRB)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRB, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+                Store(One,Local0)
+        }
+                                               // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRB,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)                           // Return Buf0
+    }                                          // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRB)
+    }                                           // End of _SRS Method
+}
+
+Device(LNKC)                                    // PCI IRQ link C
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 3)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRC, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRC, 0x80,PIRC)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRC, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }                                      // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRC,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)                           // Return Buf0
+    }                                          // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRC)
+    }                                               // End of _SRS Method
+}
+
+Device(LNKD)                                        // PCI IRQ link D
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 4)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRD, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRD, 0x80,PIRD)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRD, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }  // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRD,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)        // Return Buf0
+    }                  // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRD)
+    }                  // End of _SRS Method
+}
+
+Device(LNKE)           // PCI IRQ link E
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 5)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRE, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRE, 0x80, PIRE)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRE, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }
+                                                    // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRE,0x0F),IRQW)       // Save in buffer
+        Return(BUF0)                                // Return Buf0
+    }                                               // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRE)
+    }                                                  // End of _SRS Method
+}
+
+Device(LNKF)            // PCI IRQ link F
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 6)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRF, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRB, 0x80,PIRF)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRF, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+                Store(One,Local0)
+        }
+                                               // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRF,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)                           // Return Buf0
+    }                                          // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRF)
+    }                                                   // End of _SRS Method
+}
+
+Device(LNKG)                                            // PCI IRQ link G
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 7)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRG, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRG, 0x80,PIRG)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRG, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }                                      // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRG,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)                           // Return Buf0
+    }                                          // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRG)
+    }                                               // End of _SRS Method
+}
+
+Device(LNKH)                                        // PCI IRQ link H
+{
+    Name(_HID,EISAID("PNP0C0F"))
+
+    Name(_UID, 8)
+
+    Method(_STA,0,NotSerialized)
+    {
+        If(And(PIRH, 0x80))
+        {
+          Return(0x9)
+        }
+        Else
+        {
+          Return(0xB)
+        }    // Don't display
+    }
+
+    Method(_DIS,0,NotSerialized)
+    {
+        Or(PIRH, 0x80,PIRH)
+    }
+
+    Method(_CRS,0,Serialized)
+    {
+        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(PIRH, 0x80))
+        {
+            Store(Zero, Local0)
+        }
+        Else
+        {
+            Store(One,Local0)
+        }  // Shift 1 by value in register 70
+        ShiftLeft(Local0,And(PIRH,0x0F),IRQW)  // Save in buffer
+        Return(BUF0)   // Return Buf0
+    }                  // End of _CRS method
+
+    Name(_PRS,
+        ResourceTemplate()
+        {IRQ(Level,ActiveLow,Shared){12,11,10,9,7,5,4,3}})
+
+    Method(_SRS,1,NotSerialized)
+    {
+        CreateWordField (ARG0, 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, PIRH)
+    }                  // End of _SRS Method
+}
+
+#endif

+ 127 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/PcieExpansionPrt.asi

@@ -0,0 +1,127 @@
+/** @file
+PCI express expansion ports
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PcieExpansionPrt_asi
+#define PcieExpansionPrt_asi
+
+Device (PEX0)    // PCI express bus bridged from [Bus 0, Device 23, Function 0]
+{
+    Name(_ADR,0x00170000)            // Device (HI WORD)=23, Func (LO WORD)=0
+    Name(_PRW,Package(){0x11,0x03})  // GPE pin 0x11, Wake from S3 -- PCI PME#
+
+    OperationRegion (PES0,PCI_Config,0x40,0xA0)
+    Field (PES0, AnyAcc, NoLock, Preserve)
+    {
+    Offset(0x1A),              // SLSTS - Slot Status Register
+    ABP0,  1,                  // Bit 0, Attention Button Pressed
+    ,  2,
+    PDC0,  1,                  // Bit 3, Presence Detect Changed
+    ,  2,
+    PDS0,  1,                  // Bit 6, Presence Detect State
+    , 1,
+    LSC0,  1,                  // Bit 8, Link Active State Changed
+    offset (0x20),
+    , 16,
+    PMS0, 1,                   // Bit 16, PME Status
+    offset (0x98),
+    , 30,
+    HPE0, 1,                   // Bit 30, Hot Plug SCI Enable
+    PCE0, 1,                   // Bit 31, Power Management SCI Enable.
+    , 30,
+    HPS0, 1,                   // Bit 30, Hot Plug SCI Status
+    PCS0, 1,                   // Bit 31, Power Management SCI Status.
+    }
+
+    Method(_PRT,0,NotSerialized) {
+        If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+        {
+            Return (
+                Package()
+                {
+                    // Port 0: INTA->PIRQE,INTB->PIRQF,INTC->PIRQG,INTD->PIRQH
+                    Package() {0x0000ffff, 0, \_SB_.PCI0.LPC.LNKE, 0}, // PCI Slot 1
+                    Package() {0x0000ffff, 1, \_SB_.PCI0.LPC.LNKF, 0},
+                    Package() {0x0000ffff, 2, \_SB_.PCI0.LPC.LNKG, 0},
+                    Package() {0x0000ffff, 3, \_SB_.PCI0.LPC.LNKH, 0},
+                }
+            )
+        }
+        else    // IOAPIC Routing
+        {
+            Return (
+                Package()
+                {
+                    // Port 0: INTA->PIRQE,INTB->PIRQF,INTC->PIRQG,INTD->PIRQH
+                    Package() {0x0000ffff, 0, 0, 20}, // PCI Slot 1
+                    Package() {0x0000ffff, 1, 0, 21},
+                    Package() {0x0000ffff, 2, 0, 22},
+                    Package() {0x0000ffff, 3, 0, 23},
+                }
+            )
+        }
+    }
+}
+
+Device (PEX1)    // PCI express bus bridged from [Bus 0, Device 23, Function 1]
+{
+    Name(_ADR,0x00170001)            // Device (HI WORD)=23, Func (LO WORD)=1
+    Name(_PRW,Package(){0x11,0x03})  // GPE pin 0x11, Wake from S3 -- PCI PME#
+    OperationRegion (PES1,PCI_Config,0x40,0xA0)
+    Field (PES1, AnyAcc, NoLock, Preserve)
+    {
+    Offset(0x1A),              // SLSTS - Slot Status Register
+    ABP1,  1,                  // Bit 0, Attention Button Pressed
+    ,  2,
+    PDC1,  1,                  // Bit 3, Presence Detect Changed
+    ,  2,
+    PDS1,  1,                  // Bit 6, Presence Detect State
+    , 1,
+    LSC1,  1,                  // Bit 8, Link Active State Changed
+    offset (0x20),
+    , 16,
+    PMS1, 1,                   // Bit 16, PME Status
+    offset (0x98),
+    , 30,
+    HPE1, 1,                   // Bit 30, Hot Plug SCI Enable
+    PCE1, 1,                   // Bit 31, Power Management SCI Enable.
+    , 30,
+    HPS1, 1,                   // Bit 30, Hot Plug SCI Status
+    PCS1, 1,                   // Bit 31, Power Management SCI Status.
+    }
+    Method(_PRT,0,NotSerialized) {
+        If (LEqual(\GPIC, Zero)) // 8259 Interrupt Routing
+        {
+            Return (
+                Package()
+                {
+                    // Port 1: INTA->PIRQF,INTB->PIRQG,INTC->PIRQH,INTD->PIRQE
+                    Package() {0x0000ffff, 0, \_SB_.PCI0.LPC.LNKF, 0},
+                    Package() {0x0000ffff, 1, \_SB_.PCI0.LPC.LNKG, 0},
+                    Package() {0x0000ffff, 2, \_SB_.PCI0.LPC.LNKH, 0},
+                    Package() {0x0000ffff, 3, \_SB_.PCI0.LPC.LNKE, 0},
+                }
+            )
+        }
+        else    // IOAPIC Routing
+        {
+            Return (
+                Package()
+                {
+                    // Port 1: INTA->PIRQF,INTB->PIRQG,INTC->PIRQH,INTD->PIRQE
+                    Package() {0x0000ffff, 0, 0, 21},
+                    Package() {0x0000ffff, 1, 0, 22},
+                    Package() {0x0000ffff, 2, 0, 23},
+                    Package() {0x0000ffff, 3, 0, 20},
+                }
+            )
+        }
+    }
+}
+
+#endif

+ 347 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Platform.asl

@@ -0,0 +1,347 @@
+/** @file
+Contains root level name space objects for the platform
+
+Copyright (c) 2013-2019 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// OS TYPE DEFINITION
+//
+#define WINDOWS_XP          0x01
+#define WINDOWS_XP_SP1      0x02
+#define WINDOWS_XP_SP2      0x04
+#define WINDOWS_2003        0x08
+#define WINDOWS_Vista       0x10
+#define WINDOWS_WIN7        0x11
+#define WINDOWS_WIN8        0x12
+#define WINDOWS_WIN8_1      0x13
+#define LINUX               0xF0
+
+//
+// GPIO Interrupt Connection Resource Descriptor (GpioInt) usage.
+// GpioInt() descriptors maybe used in this file and included .asi files.
+//
+// The mapping below was provided by the first OS user that requested
+// GpioInt() support.
+// Other OS users that need GpioInt() support must use the following mapping.
+//
+#define QUARK_GPIO8_MAPPING         0x00
+#define QUARK_GPIO9_MAPPING         0x01
+#define QUARK_GPIO_SUS0_MAPPING     0x02
+#define QUARK_GPIO_SUS1_MAPPING     0x03
+#define QUARK_GPIO_SUS2_MAPPING     0x04
+#define QUARK_GPIO_SUS3_MAPPING     0x05
+#define QUARK_GPIO_SUS4_MAPPING     0x06
+#define QUARK_GPIO_SUS5_MAPPING     0x07
+#define QUARK_GPIO0_MAPPING         0x08
+#define QUARK_GPIO1_MAPPING         0x09
+#define QUARK_GPIO2_MAPPING         0x0A
+#define QUARK_GPIO3_MAPPING         0x0B
+#define QUARK_GPIO4_MAPPING         0x0C
+#define QUARK_GPIO5_MAPPING         0x0D
+#define QUARK_GPIO6_MAPPING         0x0E
+#define QUARK_GPIO7_MAPPING         0x0F
+
+DefinitionBlock (
+  "Platform.aml",
+  "DSDT",
+  1,
+  "INTEL ",
+  "QuarkNcS",
+  3)
+{
+    //
+    // Global Variables
+    //
+    Name(\GPIC, 0x0)
+
+    //
+    // Port 80
+    //
+    OperationRegion (DBG0, SystemIO, 0x80, 1)
+    Field (DBG0, ByteAcc, NoLock, Preserve)
+    { IO80,8 }
+
+    //
+    // Access CMOS range
+    //
+    OperationRegion (ACMS, SystemIO, 0x72, 2)
+    Field (ACMS, ByteAcc, NoLock, Preserve)
+    { INDX, 8, DATA, 8 }
+
+    //
+    // Global NVS Memory Block
+    //
+    OperationRegion (MNVS, SystemMemory, 0xFFFF0000, 512)
+    Field (MNVS, ByteAcc, NoLock, Preserve)
+    {
+      OSTP, 32,
+      CFGD, 32,
+      HPEA, 32,  // HPET Enabled ?
+
+      P1BB, 32,  // Pm1blkIoBaseAddress;
+      PBAB, 32,  // PmbaIoBaseAddress;
+      GP0B, 32,  // Gpe0blkIoBaseAddress;
+      GPAB, 32,  // GbaIoBaseAddress;
+
+      SMBB, 32,  // SmbaIoBaseAddress;
+      NRV1, 32,  // GNVS reserved field 1.
+      WDTB, 32,  // WdtbaIoBaseAddress;
+
+      HPTB, 32,  // HpetBaseAddress;
+      HPTS, 32,  // HpetSize;
+      PEXB, 32,  // PciExpressBaseAddress;
+      PEXS, 32,  // PciExpressSize;
+
+      RCBB, 32,  // RcbaMmioBaseAddress;
+      RCBS, 32,  // RcbaMmioSize;
+      APCB, 32,  // IoApicBaseAddress;
+      APCS, 32,  // IoApicSize;
+
+      TPMP, 32,  // TpmPresent ?
+      DBGP, 32,  // DBG2 Present?
+      PTYP, 32,  // Set to one of EFI_PLATFORM_TYPE enums.
+      ALTS, 32,  // Use alternate I2c SLA addresses.
+    }
+
+    OperationRegion (GPEB, SystemIO, 0x1100, 0x40)  //GPE Block
+    Field (GPEB, AnyAcc, NoLock, Preserve)
+    {
+      Offset(0x10),
+      SMIE, 32,                 // SMI Enable
+      SMIS, 32,                 // SMI Status
+    }
+
+    //
+    //  Processor Objects
+    //
+    Scope(\_PR) {
+        //
+        // IO base will be updated at runtime with search key "PRIO"
+        //
+        Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
+    }
+
+    //
+    // System Sleep States
+    //
+    Name (\_S0,Package (){0,0,0,0})
+    Name (\_S3,Package (){5,0,0,0})
+    Name (\_S4,Package (){6,0,0,0})
+    Name (\_S5,Package (){7,0,0,0})
+
+    //
+    //  General Purpose Event
+    //
+    Scope(\_GPE)
+    {
+        //
+        // EGPE generated GPE
+        //
+        Method(_L0D, 0x0, NotSerialized)
+        {
+            //
+            // Check EGPE for this wake event
+            //
+            Notify (\_SB.SLPB, 0x02)
+
+        }
+
+        //
+        // GPIO generated GPE
+        //
+        Method(_L0E, 0x0, NotSerialized)
+        {
+            //
+            // Check GPIO for this wake event
+            //
+            Notify (\_SB.PWRB, 0x02)
+
+        }
+
+        //
+        // SCLT generated GPE
+        //
+        Method(_L0F, 0x0, NotSerialized)
+        {
+            //
+            // Check SCLT for this wake event
+            //
+            Notify (\_SB.PCI0.SDIO, 0x02)
+            Notify (\_SB.PCI0.URT0, 0x02)
+            Notify (\_SB.PCI0.USBD, 0x02)
+            Notify (\_SB.PCI0.EHCI, 0x02)
+            Notify (\_SB.PCI0.OHCI, 0x02)
+            Notify (\_SB.PCI0.URT1, 0x02)
+            Notify (\_SB.PCI0.ENT0, 0x02)
+            Notify (\_SB.PCI0.ENT1, 0x02)
+            Notify (\_SB.PCI0.SPI0, 0x02)
+            Notify (\_SB.PCI0.SPI1, 0x02)
+            Notify (\_SB.PCI0.GIP0, 0x02)
+
+        }
+
+        //
+        // Remote Management Unit generated GPE
+        //
+        Method(_L10, 0x0, NotSerialized)
+        {
+            //
+            // Check Remote Management Unit for this wake event.
+            //
+        }
+
+        //
+        // PCIE generated GPE
+        //
+        Method(_L11, 0x0, NotSerialized)
+        {
+            //
+            // Check PCIE for this wake event
+            //
+            Notify (\_SB.PCI0.PEX0, 0x02)
+            Notify (\_SB.PCI0.PEX1, 0x02)
+        }
+    }
+
+    //
+    // define Sleeping button as mentioned in ACPI spec 2.0
+    //
+    Device (\_SB.SLPB)
+    {
+        Name (_HID, EISAID ("PNP0C0E"))
+        Method (_PRW, 0, NotSerialized)
+        {
+            Return (Package (0x02) {0x0D,0x04})
+        }
+    }
+
+    //
+    // define Power Button
+    //
+     Device (\_SB.PWRB)
+    {
+        Name (_HID, EISAID ("PNP0C0C"))
+        Method (_PRW, 0, NotSerialized)
+        {
+            Return (Package (0x02) {0x0E,0x04})
+        }
+    }
+    //
+    // System Wake up
+    //
+    Method(_WAK, 1, Serialized)
+    {
+       // Do nothing here
+       Return (0)
+    }
+
+    //
+    // System sleep down
+    //
+    Method (_PTS, 1, NotSerialized)
+    {
+        // Get ready for S3 sleep
+        if (Lequal(Arg0,3))
+        {
+                Store(0xffffffff,SMIS)     // clear SMI status
+                Store(SMIE, Local0)        // SMI Enable
+                Or(Local0,0x4,SMIE)        // Generate SMI on sleep
+        }
+    }
+
+    //
+    // Determing PIC mode
+    //
+    Method(\_PIC, 1, NotSerialized)
+    {
+        Store(Arg0,\GPIC)
+    }
+
+    //
+    //  System Bus
+    //
+    Scope(\_SB)
+    {
+        Device(PCI0)
+        {
+            Name(_HID,EISAID ("PNP0A08"))          // PCI Express Root Bridge
+            Name(_CID,EISAID ("PNP0A03"))          // Compatible PCI Root Bridge
+
+            Name(_ADR,0x00000000)                  // Device (HI WORD)=0, Func (LO WORD)=0
+            Method (_INI)
+            {
+                Store(LINUX, OSTP)                 // Set the default os is Linux
+                If (CondRefOf (_OSI))
+                {
+                    //
+                    //_OSI is supported, so it is WinXp or Win2003Server
+                    //
+                    If (\_OSI("Windows 2001"))
+                    {
+                        Store (WINDOWS_XP, OSTP)
+                    }
+                    If (\_OSI("Windows 2001 SP1"))
+                    {
+                        Store (WINDOWS_XP_SP1, OSTP)
+                    }
+                    If (\_OSI("Windows 2001 SP2"))
+                    {
+                        Store (WINDOWS_XP_SP2, OSTP)
+                    }
+                    If (\_OSI("Windows 2001.1"))
+                    {
+                        Store (WINDOWS_2003, OSTP)
+                    }
+                    If (\_OSI("Windows 2006"))
+                    {
+                        Store (WINDOWS_Vista, OSTP)
+                    }
+                    If (\_OSI("Windows 2009"))
+                    {
+                        Store (WINDOWS_WIN7, OSTP)
+                    }
+                    If (\_OSI("Windows 2012"))
+                    {
+                        Store (WINDOWS_WIN8, OSTP)
+                    }
+                    If (\_OSI("Windows 2013"))
+                    {
+                        Store (WINDOWS_WIN8_1, OSTP)
+                    }
+                    If (\_OSI("Linux"))
+                    {
+                      Store (LINUX, OSTP)
+                    }
+                }
+            }
+
+            Include ("PciHostBridge.asi")     // PCI0 Host bridge
+            Include ("QNC.asi")               // QNC miscellaneous
+            Include ("PcieExpansionPrt.asi")  // PCIe expansion bridges/devices
+            Include ("QuarkSouthCluster.asi") // Quark South Cluster devices
+            Include ("QNCLpc.asi")            // LPC bridge device
+            Include ("QNCApic.asi")           // QNC I/O Apic device
+
+        }
+
+        //
+        // Include asi files for I2C and SPI onboard devices.
+        // Devices placed here instead of below relevant controllers.
+        // Hardware topology information is maintained by the
+        // ResourceSource arg to the I2CSerialBus/SPISerialBus macros
+        // within the device asi files.
+        //
+        Include ("Tpm.asi")          // TPM device.
+        Include ("CY8C9540A.asi")    // CY8C9540A 40Bit I/O Expander & EEPROM
+        Include ("PCAL9555A.asi")    // NXP PCAL9555A I/O expander.
+        Include ("PCA9685.asi")      // NXP PCA9685 PWM/LED controller.
+        Include ("CAT24C08.asi")     // ONSEMI CAT24C08 I2C 8KB EEPROM.
+        Include ("AD7298.asi")       // Analog devices AD7298 ADC.
+        Include ("ADC108S102.asi")   // TI ADC108S102 ADC.
+        Include ("GpioClient.asi")   // Software device to expose GPIO
+    }
+}

+ 49 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNC.asi

@@ -0,0 +1,49 @@
+/** @file
+QNC devices
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef QNC_ASI
+#define QNC_ASI
+
+Device(IOCM) // I/O controller miscellaneous
+{
+    Name(_HID,EISAID("PNP0C02"))   // System board resources device node ID
+
+    Name(CRS, ResourceTemplate()
+        {
+
+            // PCIEXBAR memory range
+            Memory32Fixed(ReadOnly, 0, 0, FIX1)
+
+            // RCRB memory range
+            Memory32Fixed(ReadOnly, 0, 0, FIX2)
+
+            // Option ROM shadow memory range
+            Memory32Fixed(ReadOnly, 0x000C0000, 0x20000)
+
+            // BIOS ROM shadow memory range
+            Memory32Fixed(ReadOnly, 0x000E0000, 0x20000)
+
+            // BIOS Firmware just below 4GByte of memory 8MBytes
+            Memory32Fixed(ReadOnly, 0xFF800000, 0x800000)
+        }
+    )
+
+    Method (_CRS, 0, NotSerialized) {
+        CreateDWordField (CRS, ^FIX1._BAS, MBR0)
+        Store(\PEXB, MBR0)
+        CreateDWordField (CRS, ^FIX1._LEN, MBR1)
+        Store(\PEXS, MBR1)
+        CreateDWordField (CRS, ^FIX2._BAS, MBR2)
+        Store(\RCBB, MBR2)
+        CreateDWordField (CRS, ^FIX2._LEN, MBR3)
+        Store(\RCBS, MBR3)
+        Return (CRS)
+    }
+}
+#endif

+ 32 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCApic.asi

@@ -0,0 +1,32 @@
+/** @file
+QNC I/O Apic devices
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef QNC_APIC_ASI
+#define QNC_APIC_ASI
+
+Device(APIC)
+{
+    Name(_HID,EISAID("PNP0003"))        // APIC resources
+
+    Name(CRS, ResourceTemplate()
+        {
+            Memory32Fixed(ReadOnly, 0, 0, FIX1) // IO APIC
+        }
+    )
+
+    Method (_CRS, 0, NotSerialized) {
+        CreateDWordField (CRS, ^FIX1._BAS, MBR0)
+        Store(\APCB, MBR0)
+        CreateDWordField (CRS, ^FIX1._LEN, MBR1)
+        Store(\APCS, MBR1)
+        Return (CRS)
+    }
+}
+
+#endif

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QNCLpc.asi

@@ -0,0 +1,23 @@
+/** @file
+Lpc devices and control methods
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef QNC_LPC_ASI
+#define QNC_LPC_ASI
+
+Device(LPC)
+{
+    Name(_ADR,0x001f0000)        // Device (HI WORD)=31, Func (LO WORD)=0
+
+    Include ("PciIrq.asi")       // PCI routing control methods
+    Include ("LpcDev.asi")       // Static Lpc device resource declaration
+}
+
+
+#endif

+ 110 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/QuarkSouthCluster.asi

@@ -0,0 +1,110 @@
+/** @file
+Quark South Cluster Devices.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef QuarkSouthCluster_asi
+#define QuarkSouthCluster_asi
+
+Device (SDIO)    // SDIO [Bus 0, Device 20, Function 0]
+{
+    Name(_ADR,0x00140000)            // Device (HI WORD)=20, Func (LO WORD)=0
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (URT0)    // UART0 [Bus 0, Device 20, Function 1]
+{
+    Name(_ADR,0x00140001)            // Device (HI WORD)=20, Func (LO WORD)=1
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (USBD)    // USB Device [Bus 0, Device 20, Function 2]
+{
+    Name(_ADR,0x00140002)            // Device (HI WORD)=20, Func (LO WORD)=2
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (EHCI)    // EHCI [Bus 0, Device 20, Function 3]
+{
+    Name(_ADR,0x00140003)            // Device (HI WORD)=20, Func (LO WORD)=3
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (OHCI)    // OHCI [Bus 0, Device 20, Function 4]
+{
+    Name(_ADR,0x00140004)            // Device (HI WORD)=20, Func (LO WORD)=4
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (URT1)    // UART1 [Bus 0, Device 20, Function 5]
+{
+    Name(_ADR,0x00140005)            // Device (HI WORD)=20, Func (LO WORD)=5
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (ENT0)    // Ethernet0 [Bus 0, Device 20, Function 6]
+{
+    Name(_ADR,0x00140006)            // Device (HI WORD)=20, Func (LO WORD)=6
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (ENT1)    // Ethernet1 [Bus 0, Device 20, Function 7]
+{
+    Name(_ADR,0x00140007)            // Device (HI WORD)=20, Func (LO WORD)=7
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (SPI0)    // SPI0 [Bus 0, Device 21, Function 0]
+{
+    Name(_ADR,0x00150000)            // Device (HI WORD)=21, Func (LO WORD)=0
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (SPI1)    // SPI1 [Bus 0, Device 21, Function 1]
+{
+    Name(_ADR,0x00150001)            // Device (HI WORD)=21, Func (LO WORD)=1
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+}
+
+Device (GIP0)    // I2C/GPIO [Bus 0, Device 21, Function 2]
+{
+    Name(_ADR,0x00150002)            // Device (HI WORD)=21, Func (LO WORD)=2
+    Name(_STA,0xF)                   // Enabled, do Display
+    Name(_PRW,Package(){0x0F,0x03})  // GPE pin 0x0F, Wake from S3 -- PCI PME#
+
+    Device(GPO_)  // GPIO Virtual Child Device- for BAR0 resources
+    {
+        Name(_ADR, 0)
+        Name(_STA, 0xf)
+        Name(_PRW, Package(0x2)
+        {
+            0xf,
+            0x3
+        })
+    }
+    Device(I2C_)  // I2C Controller Virtual Child Device- for BAR1 resources
+    {
+        Name(_ADR, 1)
+        Name(_STA, 0xf)
+        Name(_PRW, Package(0x2)
+        {
+            0xf,
+            0x3
+        })
+    }
+}
+#endif

+ 45 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Dsdt/Tpm.asi

@@ -0,0 +1,45 @@
+/** @file
+
+The Infineon SLB9645 TPM ACPI definition block.
+Provides TPM device info. and TPM presence check only.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+Device (TPM)
+{
+  //
+  // Define _HID as Infineon TPM Device, _CID as "PNP0C31" (defined in
+  // "Secure Startup-FVE and TPM Admin BIOS and Platform Requirements").
+  //
+  Name(_HID ,EISAID("INT3493"))
+  Name(_CID, EISAID("PNP0C31"))
+
+  //
+  // Readable name of this device.
+  //
+  Name (_STR, Unicode ("Infineon TPM 1.2 Device (SLB9645TT1.2)"))
+
+  //
+  // Return the resource consumed by TPM device.
+  //
+  Name (_CRS, ResourceTemplate () {
+    I2cSerialBus (0x20, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.GIP0.I2C_", 0, ResourceConsumer,,)
+  })
+
+  //
+  // Check if TPM present.
+  //
+  Method (_STA, 0)
+  {
+    if (LEqual (TPMP, 0))
+    {
+      return (0)
+    }
+    Return (0x0f)
+  }
+
+}

+ 74 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.aslc

@@ -0,0 +1,74 @@
+/** @file
+This file contains the FACS structure definition.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Statements that include other files
+//
+#include "Facs.h"
+
+EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE FACS = {
+  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+  sizeof (EFI_ACPI_2_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_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+  {
+    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,
+    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
+  }
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&FACS;
+}

+ 29 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Facs/Facs.h

@@ -0,0 +1,29 @@
+/** @file
+This file describes the contents of the ACPI Firmware ACPI Control Structure (FACS)
+.  Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+All changes to the FACS contents should be done in this file.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FACS_H_
+#define _FACS_H_
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// FACS Definitions
+//
+#define EFI_ACPI_FIRMWARE_WAKING_VECTOR 0x00000000
+#define EFI_ACPI_GLOBAL_LOCK 0x00000000
+
+#define EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS 0x00000000
+#define EFI_ACPI_X_FIRMWARE_WAKING_VECTOR 0x0000000000000000
+
+#endif

+ 102 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.h

@@ -0,0 +1,102 @@
+/** @file
+This file describes the contents of the ACPI Fixed ACPI Description Table (FADT)
+.  Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+All changes to the FADT contents should be done in this file.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FADT_H_
+#define _FADT_H_
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID           'I','N','T','E','L',' '   // OEMID 6 bytes long
+#define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('T','I','A','N','O',' ',' ',' ') // OEM table id 8 bytes long
+#define EFI_ACPI_OEM_REVISION     0x00000004
+#define EFI_ACPI_CREATOR_ID       SIGNATURE_32('I','N','T','L')
+#define EFI_ACPI_CREATOR_REVISION 0x0100000D
+
+//
+// FADT Definitions
+//
+#define PM_PROFILE      0x01
+#define INT_MODEL       0x01
+#define SCI_INT_VECTOR  0x0009
+#define ACPI_ENABLE     0x0a0
+#define ACPI_DISABLE    0x0a1
+#define S4BIOS_REQ      0x00
+#define PM1_EVT_LEN     0x04
+#define PM1_CNT_LEN     0x02
+#define PM2_CNT_LEN     0x00
+#define PM_TM_LEN       0x04
+#define GPE0_BLK_LEN    0x08
+#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     0x01
+#define DUTY_WIDTH      0x03
+#define DAY_ALRM        0x00
+#define MON_ALRM        0x00
+#define CENTURY         0x00
+#define IAPC_BOOT_ARCH  EFI_ACPI_2_0_LEGACY_DEVICES
+#define FLAG            (EFI_ACPI_1_0_WBINVD | EFI_ACPI_1_0_PROC_C1 | EFI_ACPI_1_0_SLP_BUTTON | EFI_ACPI_1_0_RTC_S4)
+#define FLAG2           (EFI_ACPI_2_0_WBINVD | EFI_ACPI_2_0_PROC_C1 | EFI_ACPI_2_0_PWR_BUTTON | EFI_ACPI_2_0_SLP_BUTTON | EFI_ACPI_2_0_RTC_S4 | EFI_ACPI_2_0_RESET_REG_SUP | EFI_ACPI_3_0_USE_PLATFORM_CLOCK)
+
+#define RESET_REG_ADDRESS_SPACE_ID     EFI_ACPI_2_0_SYSTEM_IO
+#define RESET_REG_BIT_WIDTH            0x08
+#define RESET_REG_BIT_OFFSET           0x00
+#define RESET_REG_ADDRESS              0x0000000000000CF9
+#define RESET_VALUE                    0x02
+
+#define ACPI_RUNTIME_UPDATE            0x00
+
+#define PM1a_EVT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define PM1a_EVT_BLK_BIT_WIDTH         0x20
+#define PM1a_EVT_BLK_BIT_OFFSET        0x00
+
+#define PM1b_EVT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define PM1b_EVT_BLK_BIT_WIDTH         0x00
+#define PM1b_EVT_BLK_BIT_OFFSET        0x00
+#define PM1b_EVT_BLK_ADDRESS           0x0000000000000000
+
+#define PM1a_CNT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define PM1a_CNT_BLK_BIT_WIDTH         0x10
+#define PM1a_CNT_BLK_BIT_OFFSET        0x00
+
+#define PM1b_CNT_BLK_ADDRESS_SPACE_ID  EFI_ACPI_2_0_SYSTEM_IO
+#define PM1b_CNT_BLK_BIT_WIDTH         0x00
+#define PM1b_CNT_BLK_BIT_OFFSET        0x00
+#define PM1b_CNT_BLK_ADDRESS           0x0000000000000000
+
+#define PM2_CNT_BLK_ADDRESS_SPACE_ID   EFI_ACPI_2_0_SYSTEM_IO
+#define PM2_CNT_BLK_BIT_WIDTH          0x00
+#define PM2_CNT_BLK_BIT_OFFSET         0x00
+#define PM2_CNT_BLK_ADDRESS            0x0000000000000000
+
+#define PM_TMR_BLK_ADDRESS_SPACE_ID    EFI_ACPI_2_0_SYSTEM_IO
+#define PM_TMR_BLK_BIT_WIDTH           0x20
+#define PM_TMR_BLK_BIT_OFFSET          0x00
+
+#define GPE0_BLK_ADDRESS_SPACE_ID      EFI_ACPI_2_0_SYSTEM_IO
+#define GPE0_BLK_BIT_WIDTH             0x40
+#define GPE0_BLK_BIT_OFFSET            0x00
+
+#define GPE1_BLK_ADDRESS_SPACE_ID      EFI_ACPI_2_0_SYSTEM_IO
+#define GPE1_BLK_BIT_WIDTH             0x00
+#define GPE1_BLK_BIT_OFFSET            0x00
+#define GPE1_BLK_ADDRESS               0x0000000000000000
+#endif

+ 76 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt1.0.aslc

@@ -0,0 +1,76 @@
+/** @file
+This file describes the contents of the ACPI Fixed ACPI Description Table
+(FADT).  Some additional ACPI values are defined in Acpi1_0.h and Acpi2_0.h.
+All changes to the FADT contents should be done in this file.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Fadt.h"
+
+EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE FADT = {
+  EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+  sizeof (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE),
+  EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+  0,                          // to make sum of entire table == 0
+  EFI_ACPI_OEM_ID,            // OEMID is a 6 bytes long field
+  EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
+  EFI_ACPI_OEM_REVISION,      // OEM revision number
+  EFI_ACPI_CREATOR_ID,        // ASL compiler vendor ID
+  EFI_ACPI_CREATOR_REVISION,  // ASL compiler revision number
+  0,                     // Physical addesss of FACS
+  0,                     // Physical address of DSDT
+  INT_MODEL,             // System Interrupt Model
+  RESERVED,              // reserved
+  SCI_INT_VECTOR,        // System vector of SCI interrupt
+  SMI_CMD_IO_PORT,       // Port address of SMI command port
+  ACPI_ENABLE,           // value to write to port smi_cmd to enable ACPI
+  ACPI_DISABLE,          // value to write to port smi_cmd to disable ACPI
+  S4BIOS_REQ,            // Value to write to SMI CMD port to enter the S4BIOS state
+  RESERVED,              // reserved - must be zero
+  PM1a_EVT_BLK_ADDRESS,  // Port address of Power Mgt 1a Event Reg Blk
+  PM1b_EVT_BLK_ADDRESS,  // Port address of Power Mgt 1b Event Reg Blk
+  PM1a_CNT_BLK_ADDRESS,  // Port address of Power Mgt 1a Ctrl Reg Blk
+  PM1b_CNT_BLK_ADDRESS,  // Port address of Power Mgt 1b Ctrl Reg Blk
+  PM2_CNT_BLK_ADDRESS,   // Port address of Power Mgt 2  Ctrl Reg Blk
+  PM_TMR_BLK_ADDRESS,    // Port address of Power Mgt Timer Ctrl Reg Blk
+  GPE0_BLK_ADDRESS,      // Port addr of General Purpose Event 0 Reg Blk
+  GPE1_BLK_ADDRESS,      // Port addr of General Purpose Event 1 Reg Blk
+  PM1_EVT_LEN,           // Byte Length of ports at pm1X_evt_blk
+  PM1_CNT_LEN,           // Byte Length of ports at pm1X_cnt_blk
+  PM2_CNT_LEN,           // Byte Length of ports at pm2_cnt_blk
+  PM_TM_LEN,             // Byte Length of ports at pm_tm_blk
+  GPE0_BLK_LEN,          // Byte Length of ports at gpe0_blk
+  GPE1_BLK_LEN,          // Byte Length of ports at gpe1_blk
+  GPE1_BASE,             // offset in gpe model where gpe1 events start
+  RESERVED,              // reserved
+  P_LVL2_LAT,            // worst case HW latency to enter/exit C2 state
+  P_LVL3_LAT,            // worst case HW latency to enter/exit C3 state
+  FLUSH_SIZE,            // Size of area read to flush caches
+  FLUSH_STRIDE,          // Stride used in flushing caches
+  DUTY_OFFSET,           // bit location of duty cycle field in p_cnt reg
+  DUTY_WIDTH,            // bit width of duty cycle field in p_cnt reg
+  DAY_ALRM,              // index to day-of-month alarm in RTC CMOS RAM
+  MON_ALRM,              // index to month-of-year alarm in RTC CMOS RAM
+  CENTURY,               // index to century in RTC CMOS RAM
+  RESERVED,              // reserved
+  RESERVED,              // reserved
+  RESERVED,              // reserved
+  FLAG
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&FADT;
+}

+ 157 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Fadt/Fadt2.0.aslc

@@ -0,0 +1,157 @@
+/** @file
+This file describes the contents of the ACPI Fixed ACPI Description Table
+(FADT).  Some additional ACPI values are defined in Acpi1_0.h and Acpi2_0.h.
+All changes to the FADT contents should be done in this file.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Fadt.h"
+
+EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE FADT = {
+  {
+    EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE),
+    EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+    0,                    // to make sum of entire table == 0
+    {EFI_ACPI_OEM_ID},    // OEMID is a 6 bytes long field
+    EFI_ACPI_OEM_TABLE_ID,// OEM table identification(8 bytes long)
+    EFI_ACPI_OEM_REVISION,// OEM revision number
+    EFI_ACPI_CREATOR_ID,  // ASL compiler vendor ID
+    EFI_ACPI_CREATOR_REVISION  // ASL compiler revision number
+  },
+  0,                    // Physical addesss of FACS
+  0,                    // Physical address of DSDT
+  RESERVED,             // reserved
+  PM_PROFILE,           // Preferred powermanagement profile
+  SCI_INT_VECTOR,       // System vector of SCI interrupt
+  ACPI_RUNTIME_UPDATE,  // Port address of SMI command port
+  ACPI_ENABLE,          // value to write to port smi_cmd to enable ACPI
+  ACPI_DISABLE,         // value to write to port smi_cmd to disable ACPI
+  S4BIOS_REQ,           // Value to write to SMI CMD port to enter the S4BIOS state
+  RESERVED,             // reserved - must be zero
+  ACPI_RUNTIME_UPDATE,  // Port address of Power Mgt 1a Event Reg Blk
+  PM1b_EVT_BLK_ADDRESS, // Port address of Power Mgt 1b Event Reg Blk
+  ACPI_RUNTIME_UPDATE,  // Port address of Power Mgt 1a Ctrl Reg Blk
+  PM1b_CNT_BLK_ADDRESS, // Port address of Power Mgt 1b Ctrl Reg Blk
+  ACPI_RUNTIME_UPDATE,  // Port address of Power Mgt 2  Ctrl Reg Blk
+  ACPI_RUNTIME_UPDATE,  // Port address of Power Mgt Timer Ctrl Reg Blk
+  ACPI_RUNTIME_UPDATE,  // Port addr of General Purpose Event 0 Reg Blk
+  GPE1_BLK_ADDRESS,     // Port addr of General Purpose Event 1 Reg Blk
+  PM1_EVT_LEN,          // Byte Length of ports at pm1X_evt_blk
+  PM1_CNT_LEN,          // Byte Length of ports at pm1X_cnt_blk
+  PM2_CNT_LEN,          // Byte Length of ports at pm2_cnt_blk
+  PM_TM_LEN,            // Byte Length of ports at pm_tm_blk
+  GPE0_BLK_LEN,         // Byte Length of ports at gpe0_blk
+  GPE1_BLK_LEN,         // Byte Length of ports at gpe1_blk
+  GPE1_BASE,            // offset in gpe model where gpe1 events start
+  RESERVED,             // reserved
+  P_LVL2_LAT,           // worst case HW latency to enter/exit C2 state
+  P_LVL3_LAT,           // worst case HW latency to enter/exit C3 state
+  FLUSH_SIZE,           // Size of area read to flush caches
+  FLUSH_STRIDE,         // Stride used in flushing caches
+  DUTY_OFFSET,          // bit location of duty cycle field in p_cnt reg
+  DUTY_WIDTH,           // bit width of duty cycle field in p_cnt reg
+  DAY_ALRM,             // index to day-of-month alarm in RTC CMOS RAM
+  MON_ALRM,             // index to month-of-year alarm in RTC CMOS RAM
+  CENTURY,              // index to century in RTC CMOS RAM
+  IAPC_BOOT_ARCH,       // IA-PC Boot Architecture Flags
+  RESERVED,             // reserved
+  FLAG2,                // Fixed feature flags
+
+  {
+    RESET_REG_ADDRESS_SPACE_ID,  // Address of the reset register
+    RESET_REG_BIT_WIDTH,
+    RESET_REG_BIT_OFFSET,
+    RESERVED,
+    RESET_REG_ADDRESS
+  },
+  RESET_VALUE,          // Value to write to the RESET_REG port
+  {
+    RESERVED,
+    RESERVED,
+    RESERVED
+  },
+  0,                // 64Bit physical addesss of FACS
+  0,                // 64Bit physical address of DSDT
+
+  {
+    PM1a_EVT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1a Event Reg Blk
+    PM1a_EVT_BLK_BIT_WIDTH,
+    PM1a_EVT_BLK_BIT_OFFSET,
+    RESERVED,
+    ACPI_RUNTIME_UPDATE
+  },
+
+  {
+    PM1b_EVT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1b Event Reg Blk
+    PM1b_EVT_BLK_BIT_WIDTH,
+    PM1b_EVT_BLK_BIT_OFFSET,
+    RESERVED,
+    PM1b_EVT_BLK_ADDRESS
+  },
+
+  {
+    PM1a_CNT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1a Ctrl Reg Blk
+    PM1a_CNT_BLK_BIT_WIDTH,
+    PM1a_CNT_BLK_BIT_OFFSET,
+    RESERVED,
+    ACPI_RUNTIME_UPDATE
+  },
+
+  {
+    PM1b_CNT_BLK_ADDRESS_SPACE_ID, // Extended Port address of Power Mgt 1b Ctrl Reg Blk
+    PM1b_CNT_BLK_BIT_WIDTH,
+    PM1b_CNT_BLK_BIT_OFFSET,
+    RESERVED,
+    PM1b_CNT_BLK_ADDRESS
+  },
+
+  {
+    PM2_CNT_BLK_ADDRESS_SPACE_ID,  // Extended Port address of Power Mgt 2  Ctrl Reg Blk
+    PM2_CNT_BLK_BIT_WIDTH,
+    PM2_CNT_BLK_BIT_OFFSET,
+    RESERVED,
+    ACPI_RUNTIME_UPDATE
+  },
+
+  {
+    PM_TMR_BLK_ADDRESS_SPACE_ID,   // Extended Port address of Power Mgt Timer Ctrl Reg Blk
+    PM_TMR_BLK_BIT_WIDTH,
+    PM_TMR_BLK_BIT_OFFSET,
+    RESERVED,
+    ACPI_RUNTIME_UPDATE
+  },
+
+  {
+    GPE0_BLK_ADDRESS_SPACE_ID,   // Extended Port address of General Purpose Event 0 Reg Blk
+    GPE0_BLK_BIT_WIDTH,
+    GPE0_BLK_BIT_OFFSET,
+    RESERVED,
+    ACPI_RUNTIME_UPDATE
+  },
+
+  {
+    GPE1_BLK_ADDRESS_SPACE_ID,   // Extended Port address of General Purpose Event 1 Reg Blk
+    GPE1_BLK_BIT_WIDTH,
+    GPE1_BLK_BIT_OFFSET,
+    RESERVED,
+    GPE1_BLK_ADDRESS
+  }
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&FADT;
+}

+ 68 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.aslc

@@ -0,0 +1,68 @@
+/** @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.  The table layout is defined in
+HighPrecisionEventTimerTable.h and the table contents are defined in Acpi1.0.h and Hpet.h.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Statements that include other files
+//
+
+#include "Hpet.h"
+
+//
+// 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,
+    ACPI_RUNTIME_UPDATE
+  },
+  EFI_ACPI_HPET_NUMBER,
+  EFI_ACPI_MIN_CLOCK_TICK,
+  EFI_ACPI_HPET_ATTRIBUTES
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&Hpet;
+}

+ 45 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.h

@@ -0,0 +1,45 @@
+/** @file
+This file describes the contents of the ACPI High Precision Event Timer Description Table
+(HPET).  Some additional ACPI values are defined in Acpi10.h, Acpi20.h, and Acpi30.h
+All changes to the HPET contents should be done in this file.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _HPET_H_
+#define _HPET_H_
+
+//
+// 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                   0x8086A201
+
+#define ACPI_RUNTIME_UPDATE                             0x00
+
+//
+// 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            0x00
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET           0x00
+#define EFI_ACPI_EVENT_TIMER_ACCESS_SIZE                0x00
+
+#define EFI_ACPI_HPET_NUMBER                            0x00
+
+#define EFI_ACPI_MIN_CLOCK_TICK                         0x0080
+
+#define EFI_ACPI_HPET_ATTRIBUTES                        0x00
+
+#endif

+ 75 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.aslc

@@ -0,0 +1,75 @@
+/** @file
+This file contains a structure definition for the ACPI Memory Mapped Configuration
+Address Space table (MCFG).  Any changes to the number of entries in the table require
+updating the structure count in Mcfg.h and then adding the structure to the
+MCFG defined in this file.  The table layout is defined in Mcfg.h and the
+table contents are defined in the MemoryMappedConfigurationSpaceAccessTable.h.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Statements that include other files
+//
+
+#include "Mcfg.h"
+
+//
+// Multiple APIC Description Table
+//
+
+EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
+  {
+    EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
+    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+
+    //
+    // Checksum will be updated at runtime
+    //
+    0x00,
+
+    //
+    // It is expected that these values will be programmed at runtime
+    //
+    {' ', ' ', ' ', ' ', ' ', ' '},
+
+    0,
+    EFI_ACPI_OEM_MCFG_REVISION,
+    0,
+    0
+  },
+  //
+  // Reserved
+  //
+  0x0000000000000000,
+
+  //
+  // MCFG specific fields
+  //
+
+  {
+    {
+      0x00000000,                                                   // BaseAddress (will be updated at runtime)
+      0x0000,                                                       // PciSegmentGroupNumber
+      0x00,                                                         // StartBusNumber
+      0x1F,                                                         // EndBusNumber
+      0x00000000                                                    // Reserved
+    }
+  }
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&Mcfg;
+}

+ 56 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/AcpiTables/Mcfg/Mcfg.h

@@ -0,0 +1,56 @@
+/** @file
+This file describes the contents of the ACPI Memory Mapped Configuration
+Space Access Table (MCFG).  Some additional ACPI values are defined in Acpi10.h,
+Acpi20.h, and Acpi30.h.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MCFG_H_
+#define _MCFG_H_
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+//
+// MCFG Definitions
+//
+
+#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001
+
+//
+// Define the number of allocation structures so that we can build the table structure.
+//
+
+#define EFI_ACPI_ALLOCATION_STRUCTURE_COUNT           1
+
+//
+// MCFG structure
+//
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// MCFG Table structure
+//
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER                                                            Header;
+  UINT64                                                                                 Reserved;
+#if EFI_ACPI_ALLOCATION_STRUCTURE_COUNT > 0
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE  AllocationStructure[EFI_ACPI_ALLOCATION_STRUCTURE_COUNT];
+#endif
+} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+#endif

+ 1402 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.c

@@ -0,0 +1,1402 @@
+/** @file
+Update the _PRT and _PRW method for pci devices
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#include "AcpiPlatform.h"
+
+PCI_DEVICE_INFO *mQNCPciInfo = NULL;
+
+/**
+  Init Pci Device Structure
+  @param mConfigData    - Pointer of Pci Device information Structure
+
+**/
+VOID
+InitPciDeviceInfoStructure (
+  PCI_DEVICE_SETTING            *mConfigData
+  )
+{
+  //
+  // Return 0 given that function unsupported.
+  // Would need to parse ACPI tables and build mQNCPciInfo above
+  // with found _PRT & _PRW methods for PCI devices.
+  //
+  mConfigData->PciDeviceInfoNumber = 0;
+}
+
+/**
+  return Integer value.
+
+  @param Data    - AML data buffer
+  @param Integer - integer value.
+
+  @return Data size processed.
+**/
+UINTN
+SdtGetInteger (
+  IN  UINT8  *Data,
+  OUT UINT64 *Integer
+  )
+{
+  *Integer = 0;
+  switch (*Data) {
+  case AML_ZERO_OP:
+    return 1;
+  case AML_ONE_OP:
+    *Integer = 1;
+    return 1;
+  case AML_ONES_OP:
+    *Integer = (UINTN)-1;
+    return 1;
+  case AML_BYTE_PREFIX:
+    CopyMem (Integer, Data + 1, sizeof(UINT8));
+    return 1 + sizeof(UINT8);
+  case AML_WORD_PREFIX:
+    CopyMem (Integer, Data + 1, sizeof(UINT16));
+    return 1 + sizeof(UINT16);
+  case AML_DWORD_PREFIX:
+    CopyMem (Integer, Data + 1, sizeof(UINT32));
+    return 1 + sizeof(UINT32);
+  case AML_QWORD_PREFIX:
+    CopyMem (Integer, Data + 1, sizeof(UINT64));
+    return 1 + sizeof(UINT64);
+  default:
+    // Something wrong
+    ASSERT (FALSE);
+    return 1;
+  }
+}
+
+
+/**
+  Check if this handle has expected opcode.
+
+  @param AcpiSdt    Pointer to Acpi SDT protocol
+  @param Handle     ACPI handle
+  @param OpCode     Expected OpCode
+  @param SubOpCode  Expected SubOpCode
+
+  @retval TRUE  This handle has expected opcode
+  @retval FALSE This handle does not have expected opcode
+**/
+BOOLEAN
+SdtIsThisTypeObject (
+  IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+  IN EFI_ACPI_HANDLE Handle,
+  IN UINT8           OpCode,
+  IN UINT8           SubOpCode
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+
+  Status = AcpiSdt->GetOption (Handle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  if (OpCode == AML_EXT_OP) {
+    if (Data[1] == SubOpCode) {
+      return TRUE;
+    }
+  } else {
+    if (Data[0] == OpCode) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Check if this handle has expected name and name value.
+
+  @param AcpiSdt    Pointer to Acpi SDT protocol
+  @param Handle     ACPI handle
+  @param Name       Expected name
+  @param Value      Expected name value
+
+  @retval TRUE  This handle has expected name and name value.
+  @retval FALSE This handle does not have expected name and name value.
+**/
+BOOLEAN
+SdtIsNameIntegerValueEqual (
+  IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+  IN EFI_ACPI_HANDLE Handle,
+  IN CHAR8           *Name,
+  IN UINT64          Value
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  UINT64             Integer;
+
+  Status = AcpiSdt->GetOption (Handle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+  if (CompareMem (Data, Name, 4) != 0) {
+    return FALSE;
+  }
+
+  //
+  // Name match check object
+  //
+  Status = AcpiSdt->GetOption (Handle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+
+  Integer = 0;
+  SdtGetInteger (Data, &Integer);
+  if (Integer != Value) {
+    return FALSE;
+  }
+
+  // All match
+  return TRUE;
+}
+
+/**
+  Check if this handle's children has expected name and name value.
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param ParentHandle     ACPI parent handle
+  @param Name             Expected name
+  @param Value            Expected name value
+
+  @retval TRUE  This handle's children has expected name and name value.
+  @retval FALSE This handle's children does not have expected name and name value.
+**/
+BOOLEAN
+SdtCheckNameIntegerValue (
+  IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt,
+  IN EFI_ACPI_HANDLE ParentHandle,
+  IN CHAR8           *Name,
+  IN UINT64          Value
+  )
+{
+  EFI_ACPI_HANDLE PreviousHandle;
+  EFI_ACPI_HANDLE Handle;
+  EFI_STATUS      Status;
+
+  Handle = NULL;
+  while (TRUE) {
+    PreviousHandle = Handle;
+    Status = AcpiSdt->GetChild (ParentHandle, &Handle);
+    ASSERT_EFI_ERROR (Status);
+
+    if (PreviousHandle != NULL) {
+      Status = AcpiSdt->Close (PreviousHandle);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    //
+    // Done
+    //
+    if (Handle == NULL) {
+      return FALSE;
+    }
+
+    //
+    // Check this name
+    //
+    if (SdtIsThisTypeObject (AcpiSdt, Handle, AML_NAME_OP, 0)) {
+      if (SdtIsNameIntegerValueEqual (AcpiSdt, Handle, Name, Value)) {
+        return TRUE;
+      }
+    }
+  }
+
+  //
+  // Should not run here
+  //
+}
+
+/**
+  Convert the pci address from VPD (bus,dev,fun) into the address that acpi table
+  can recognize.
+
+  @param PciAddress    Pci address from VPD
+
+  @retval return the address that acpi table can recognize
+**/
+UINT32
+SdtConvertToAcpiPciAdress (
+  IN UINT32 PciAddress
+  )
+{
+  UINT32 ReturnAddress;
+
+  ReturnAddress = ((PciAddress & 0x0000FF00) << 8) | (PciAddress & 0x000000FF);
+
+  if ((PciAddress & 0x000000FF) == 0x000000FF)
+    ReturnAddress |= 0x0000FFFF;
+
+  return ReturnAddress;
+}
+
+/**
+  return AML NameString size.
+
+  @param Buffer - AML name string
+
+  @return AML name string size
+**/
+UINTN
+SdtGetNameStringSize (
+  IN UINT8              *Buffer
+  )
+{
+  UINTN                 SegCount;
+  UINTN                 Length;
+
+  Length = 0;
+
+  //
+  // Parse root or prefix
+  //
+  if (*Buffer == AML_ROOT_CHAR) {
+    //
+    // RootChar
+    //
+    Buffer ++;
+    Length ++;
+  } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
+    //
+    // ParentPrefixChar
+    //
+    Buffer ++;
+    Length ++;
+    while (*Buffer == AML_PARENT_PREFIX_CHAR) {
+      Buffer ++;
+      Length ++;
+    }
+  }
+
+  //
+  // Parse name segment
+  //
+  if (*Buffer == AML_DUAL_NAME_PREFIX) {
+    //
+    // DualName
+    //
+    Buffer ++;
+    Length ++;
+    SegCount = 2;
+  } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
+    //
+    // MultiName
+    //
+    Buffer ++;
+    Length ++;
+    SegCount = *Buffer;
+    Buffer ++;
+    Length ++;
+  } else if (*Buffer == 0) {
+    //
+    // NULL Name
+    //
+    SegCount = 0;
+    Length ++;
+  } else {
+    //
+    // NameSeg
+    //
+    SegCount = 1;
+  }
+
+  Buffer += 4 * SegCount;
+  Length += 4 * SegCount;
+
+  return Length;
+}
+
+/**
+  The routine to check if this device is PCI root bridge.
+
+  @param AcpiSdt       Pointer to Acpi SDT protocol
+  @param DeviceHandle  ACPI device handle
+  @param Context       Context info - not used here
+
+  @retval TRUE  This is PCI root bridge
+  @retval FALSE This is not PCI root bridge
+**/
+BOOLEAN
+SdtFindRootBridgeHandle (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        CheckHandle,
+  IN VOID                   *Context
+  )
+{
+  BOOLEAN            Result;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  EFI_STATUS         Status;
+
+  if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
+    return FALSE;
+
+  Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_HID", (UINT64)0x080AD041); // PNP0A08
+  if (!Result) {
+    Result = SdtCheckNameIntegerValue (AcpiSdt, CheckHandle, "_CID", (UINT64)0x030AD041); // PNP0A03
+    if (!Result) {
+      return Result;
+    }
+  }
+
+  //
+  // Found
+  //
+  Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+  return Result;
+}
+
+
+/**
+  The routine to check if this device is wanted.
+
+  @param AcpiSdt       Pointer to Acpi SDT protocol
+  @param DeviceHandle  ACPI device handle
+  @param Context       Context info - not used here
+
+  @retval TRUE  This is PCI device wanted
+  @retval FALSE This is not PCI device wanted
+**/
+BOOLEAN
+SdtFindPciDeviceHandle (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        CheckHandle,
+  IN VOID                   *Context
+  )
+{
+  BOOLEAN            Result;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  EFI_STATUS         Status;
+
+  if (!SdtIsThisTypeObject (AcpiSdt, CheckHandle, AML_EXT_OP, AML_EXT_DEVICE_OP))
+    return FALSE;
+
+  Result = SdtCheckNameIntegerValue (AcpiSdt,CheckHandle, "_ADR", (UINT64)*(UINT32 *)Context);
+  if (!Result) {
+    return Result;
+  }
+
+  //
+  // Found
+  //
+  Status = AcpiSdt->GetOption (CheckHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);
+
+  return Result;
+}
+
+/**
+  Go through the parent handle and find the handle which pass CheckHandleInfo.
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param ParentHandle     ACPI parent handle
+  @param CheckHandleInfo  The callback routine to check if this handle meet the requirement
+  @param Context          The context of CheckHandleInfo
+
+  @return the handle which is first one can pass CheckHandleInfo.
+**/
+EFI_ACPI_HANDLE
+SdtGetHandleByScanAllChilds (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        ParentHandle,
+  IN CHECK_HANDLE_INFO      CheckHandleInfo,
+  IN VOID                   *Context
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_ACPI_HANDLE    Handle;
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    ReturnHandle;
+
+  //
+  // Use deep first algo to enumerate all ACPI object
+  //
+  Handle = NULL;
+  while (TRUE) {
+    PreviousHandle = Handle;
+    Status = AcpiSdt->GetChild (ParentHandle, &Handle);
+    ASSERT_EFI_ERROR (Status);
+
+    if (PreviousHandle != NULL) {
+      Status = AcpiSdt->Close (PreviousHandle);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    //
+    // Done
+    //
+    if (Handle == NULL) {
+      return NULL;
+    }
+
+    //
+    // Check this handle
+    //
+    if (CheckHandleInfo (AcpiSdt, Handle, Context)) {
+      return Handle;
+    }
+
+    //
+    // Enumerate
+    //
+    ReturnHandle = SdtGetHandleByScanAllChilds (AcpiSdt, Handle, CheckHandleInfo, Context);
+    if (ReturnHandle != NULL) {
+      return ReturnHandle;
+    }
+  }
+
+  //
+  // Should not run here
+  //
+}
+
+
+/**
+  Check whether the INTx package is matched
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param INTxPkgHandle    ACPI INTx package handle
+  @param PciAddress       Acpi pci address
+  @param INTx             Index of INTx pin
+  @param IsAPIC           Tell whether the returned INTx package is for APIC or not
+
+  @retval       TRUE      the INTx package is matched
+  @retval       FALSE     the INTx package is not matched
+
+**/
+BOOLEAN
+SdtCheckINTxPkgIsMatch (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        INTxPkgHandle,
+  IN UINT32                 PciAddress,
+  IN UINT8                  INTx,
+  IN BOOLEAN                *IsAPIC
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    MemberHandle;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  UINT64             CurrentPciAddress;
+  UINT64             CurrentINTx;
+  UINTN              ChildSize;
+
+
+  //
+  // Check the pci address
+  //
+  MemberHandle = NULL;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  CurrentPciAddress = 0;
+  SdtGetInteger (Data, &CurrentPciAddress);
+
+  if (CurrentPciAddress != PciAddress) {
+
+    Status = AcpiSdt->Close (MemberHandle);
+    ASSERT_EFI_ERROR (Status);
+    return FALSE;
+  }
+
+  //
+  // Check the pci interrupt pin
+  //
+  PreviousHandle = MemberHandle;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  if (PreviousHandle != NULL) {
+    Status = AcpiSdt->Close (PreviousHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  CurrentINTx = 0;
+  ChildSize = SdtGetInteger (Data, &CurrentINTx);
+
+  Status = AcpiSdt->Close (MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  if (CurrentINTx != INTx)
+    return FALSE;
+
+  Data += ChildSize;
+
+  if (*Data == AML_BYTE_PREFIX)
+    Data += 1;
+
+  //
+  // Check the pci interrupt source
+  //
+  if (*Data  != 0)
+    *IsAPIC = FALSE;
+  else
+    *IsAPIC = TRUE;
+
+  return TRUE;
+}
+
+
+
+
+/**
+  Get the wanted INTx package inside the parent package
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param ParentPkgHandle  ACPI parent package handle
+  @param PciAddress       Acpi pci address
+  @param INTx             Index of INTx pin
+  @param INTxPkgHandle    ACPI INTx package handle
+  @param IsAPIC           Tell whether the returned INTx package is for APIC or not
+
+**/
+VOID
+SdtGetINTxPkgHandle (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        ParentPkgHandle,
+  IN UINT32                 PciAddress,
+  IN UINT8                  INTx,
+  IN EFI_ACPI_HANDLE        *INTxPkgHandle,
+  IN BOOLEAN                *IsAPIC
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    ChildPkgHandle;
+
+  ChildPkgHandle = NULL;
+  while (TRUE) {
+    PreviousHandle = ChildPkgHandle;
+    Status = AcpiSdt->GetChild (ParentPkgHandle, &ChildPkgHandle);
+    ASSERT_EFI_ERROR (Status);
+
+    if (PreviousHandle != NULL) {
+      Status = AcpiSdt->Close (PreviousHandle);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    if (ChildPkgHandle == NULL) {
+      break;
+    }
+
+    if (SdtCheckINTxPkgIsMatch(AcpiSdt, ChildPkgHandle, PciAddress, INTx, IsAPIC)) {
+      *INTxPkgHandle = ChildPkgHandle;
+      return;
+    }
+  }
+
+  return;
+}
+
+/**
+  Update the INTx package with the correct pirq value
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param INTxPkgHandle    ACPI INTx package handle
+  @param PirqValue        Correct pirq value
+  @param IsAPIC           Tell whether the INTx package is for APIC or not
+
+**/
+VOID
+SdtUpdateINTxPkg (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        INTxPkgHandle,
+  IN UINT8                  PirqValue,
+  IN BOOLEAN                IsAPIC
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    MemberHandle;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  UINT64             TempValue;
+  UINTN              ChildSize;
+
+
+  //
+  // Check the pci address
+  //
+  MemberHandle = NULL;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  //
+  // Check the pci interrupt pin
+  //
+  PreviousHandle = MemberHandle;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  if (PreviousHandle != NULL) {
+    Status = AcpiSdt->Close (PreviousHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  ChildSize = SdtGetInteger (Data, &TempValue);
+
+  Status = AcpiSdt->Close (MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  Data += ChildSize;
+
+  //
+  // update the pci interrupt source or source index
+  //
+  if (!IsAPIC) {
+    ChildSize = SdtGetNameStringSize (Data);
+    Data += (ChildSize - 1);
+
+    PirqValue += 0x40;   // change to ascii char
+    if (*Data != PirqValue)
+      *Data = PirqValue;
+  } else {
+
+    ChildSize = SdtGetInteger (Data, &TempValue);
+    Data += ChildSize;
+
+    Data += 1;
+
+    if (*Data != PirqValue)
+      *Data = PirqValue;
+  }
+}
+
+/**
+  Check every child package inside this interested parent package for update PRT
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param ParentPkgHandle  ACPI parent package handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckParentPackage (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        ParentPkgHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_ACPI_HANDLE    INTAPkgHandle;
+  EFI_ACPI_HANDLE    INTBPkgHandle;
+  EFI_ACPI_HANDLE    INTCPkgHandle;
+  EFI_ACPI_HANDLE    INTDPkgHandle;
+  UINT32             PciAddress = 0;
+  BOOLEAN            IsAllFunctions = FALSE;
+  UINT8              IsAPIC = 0;
+  EFI_STATUS         Status;
+
+  INTAPkgHandle = INTBPkgHandle = INTCPkgHandle = INTDPkgHandle = NULL;
+
+  PciAddress   = SdtConvertToAcpiPciAdress(PciDeviceInfo->DeviceAddress);
+
+  if ((PciAddress & 0xFFFF) == 0xFFFF) {
+    IsAllFunctions = TRUE;
+  } else {
+    IsAllFunctions = FALSE;
+    PciAddress = (PciAddress | 0xFFFF);
+  }
+
+  SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 0, &INTAPkgHandle, (BOOLEAN *)&IsAPIC);
+  SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 1, &INTBPkgHandle, (BOOLEAN *)&IsAPIC);
+  SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 2, &INTCPkgHandle, (BOOLEAN *)&IsAPIC);
+  SdtGetINTxPkgHandle (AcpiSdt, ParentPkgHandle, PciAddress, 3, &INTDPkgHandle, (BOOLEAN *)&IsAPIC);
+
+  //
+  // Check INTA
+  //
+  if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle != NULL)) {
+    //
+    // Find INTA package and there is valid INTA update item, update it
+    //
+    SdtUpdateINTxPkg (AcpiSdt, INTAPkgHandle, (PciDeviceInfo->INTA[IsAPIC]), IsAPIC);
+  } else if ((PciDeviceInfo->INTA[IsAPIC] != 0xFF) && (INTAPkgHandle == NULL)) {
+    //
+    // There is valid INTA update item, but no INA package exist, should add it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould add INTA item for this device(0x%x)\n\n", PciAddress));
+
+  } else if ((PciDeviceInfo->INTA[IsAPIC] == 0xFF) && (INTAPkgHandle != NULL) && IsAllFunctions) {
+    //
+    // For all functions senario, if there is invalid INTA update item, but INTA package does exist, should delete it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould remove INTA item for this device(0x%x)\n\n", PciAddress));
+
+  }
+
+  //
+  // Check INTB
+  //
+  if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle != NULL)) {
+    //
+    // Find INTB package and there is valid INTB update item, update it
+    //
+    SdtUpdateINTxPkg (AcpiSdt, INTBPkgHandle, (PciDeviceInfo->INTB[IsAPIC]), IsAPIC);
+  } else if ((PciDeviceInfo->INTB[IsAPIC] != 0xFF) && (INTBPkgHandle == NULL)) {
+    //
+    // There is valid INTB update item, but no INTB package exist, should add it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould add INTB item for this device(0x%x)\n\n", PciAddress));
+
+  } else if ((PciDeviceInfo->INTB[IsAPIC] == 0xFF) && (INTBPkgHandle != NULL) && IsAllFunctions) {
+    //
+    // For all functions senario, if there is invalid INTB update item, but INTB package does exist, should delete it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould remove INTB item for this device(0x%x)\n\n", PciAddress));
+
+  }
+
+  //
+  // Check INTC
+  //
+  if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle != NULL)) {
+    //
+    // Find INTC package and there is valid INTC update item, update it
+    //
+    SdtUpdateINTxPkg (AcpiSdt, INTCPkgHandle, (PciDeviceInfo->INTC[IsAPIC]), IsAPIC);
+  } else if ((PciDeviceInfo->INTC[IsAPIC] != 0xFF) && (INTCPkgHandle == NULL)) {
+    //
+    // There is valid INTC update item, but no INTC package exist, should add it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould add INTC item for this device(0x%x)\n\n", PciAddress));
+
+  } else if ((PciDeviceInfo->INTC[IsAPIC] == 0xFF) && (INTCPkgHandle != NULL) && IsAllFunctions) {
+    //
+    // For all functions senario, if there is invalid INTC update item, but INTC package does exist, should delete it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould remove INTC item for this device(0x%x)\n\n", PciAddress));
+  }
+
+  //
+  // Check INTD
+  //
+  if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle != NULL)) {
+    //
+    // Find INTD package and there is valid INTD update item, update it
+    //
+    SdtUpdateINTxPkg (AcpiSdt, INTDPkgHandle, (PciDeviceInfo->INTD[IsAPIC]), IsAPIC);
+  } else if ((PciDeviceInfo->INTD[IsAPIC] != 0xFF) && (INTDPkgHandle == NULL)) {
+    //
+    // There is valid INTD update item, but no INTD package exist, should add it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould add INTD item for this device(0x%x)\n\n", PciAddress));
+
+  }  else if ((PciDeviceInfo->INTD[IsAPIC] == 0xFF) && (INTDPkgHandle != NULL) && IsAllFunctions) {
+    //
+    // For all functions senario, if there is invalid INTD update item, but INTD package does exist, should delete it
+    //
+    DEBUG ((EFI_D_ERROR, "\n\nShould remove INTD item for this device(0x%x)\n\n", PciAddress));
+  }
+
+
+  if (INTAPkgHandle != NULL) {
+    Status = AcpiSdt->Close (INTAPkgHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  if (INTBPkgHandle != NULL) {
+    Status = AcpiSdt->Close (INTBPkgHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  if (INTCPkgHandle != NULL) {
+    Status = AcpiSdt->Close (INTCPkgHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  if (INTDPkgHandle != NULL) {
+    Status = AcpiSdt->Close (INTDPkgHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return;
+}
+
+/**
+  Check every return package for update PRT
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param ParentHandle     ACPI pci device handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckReturnPackage (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        MethodHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_ACPI_HANDLE    ReturnHandle;
+  EFI_ACPI_HANDLE    PackageHandle;
+  EFI_ACPI_HANDLE    NamePkgHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+  CHAR8              NameStr[128];
+
+  ReturnHandle = NULL;
+  while (TRUE) {
+    PreviousHandle = ReturnHandle;
+    Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle);
+    ASSERT_EFI_ERROR (Status);
+
+    if (PreviousHandle != NULL) {
+      Status = AcpiSdt->Close (PreviousHandle);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    if (ReturnHandle == NULL) {
+      break;
+    }
+
+    Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+    ASSERT_EFI_ERROR (Status);
+    ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+    if (*Data == AML_RETURN_OP) {
+      //
+      // Find the return method handle, then look for the returned package data
+      //
+      Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize);
+      ASSERT_EFI_ERROR (Status);
+
+
+      if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {
+        ZeroMem (NameStr, 128);
+        AsciiStrCpy (NameStr, "\\_SB.");
+        DataSize = SdtGetNameStringSize (Data);
+        AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize);
+
+        NamePkgHandle = NULL;
+        Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle);
+        ASSERT_EFI_ERROR (Status);
+        ASSERT (NamePkgHandle != NULL);
+
+        Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+        ASSERT_EFI_ERROR (Status);
+        ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+        ASSERT (*Data == AML_NAME_OP);
+
+        Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+        ASSERT_EFI_ERROR (Status);
+        ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+      }
+
+      ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+
+      //
+      // Get the parent package handle
+      //
+      PackageHandle = NULL;
+      Status = AcpiSdt->Open (Data, &PackageHandle);
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Check the parent package for update pci routing
+      //
+      SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo);
+
+      Status = AcpiSdt->Close (PackageHandle);
+      ASSERT_EFI_ERROR (Status);
+
+      Status = AcpiSdt->Close (ReturnHandle);
+      ASSERT_EFI_ERROR (Status);
+
+      break;
+    }
+
+    //
+    // Not ReturnOp, search it as parent
+    //
+    SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo);
+  }
+
+  //
+  // Done
+  //
+  return;
+
+}
+
+/**
+  update interrupt info inside the PRT method for the given pci device handle
+
+  @param AcpiSdt       Pointer to Acpi SDT protocol
+  @param PciHandle     ACPI pci device handle
+  @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePrtMethod (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        PciHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    PrtMethodHandle;
+
+  //
+  // Find the PRT method under this pci device
+  //
+  PrtMethodHandle = NULL;
+  Status = AcpiSdt->FindPath (PciHandle, "_PRT", &PrtMethodHandle);
+
+  if (EFI_ERROR (Status)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PrtMethodHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SdtCheckReturnPackage(AcpiSdt, PrtMethodHandle, PciDeviceInfo);
+
+  Status = AcpiSdt->Close (PrtMethodHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+
+/**
+  Update the package inside name op with correct wakeup resources
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param InPkgHandle      ACPI inside package handle
+  @param GPEPin           Correct gpe pin
+  @param SxNum            Correct system state the device can wake up from
+
+**/
+VOID
+SdtUpdatePackageInName (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        INTxPkgHandle,
+  IN UINT8                  GPEPin,
+  IN UINT8                  SxNum
+  )
+{
+  EFI_ACPI_HANDLE    PreviousHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    MemberHandle;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+
+  //
+  // Check the gpe pin
+  //
+  MemberHandle = NULL;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  //
+  // Skip byte prefix
+  //
+  Data += 1;
+
+  if (*Data != GPEPin) {
+
+    *Data = GPEPin;
+  }
+
+  //
+  // Check the sx number
+  //
+  PreviousHandle = MemberHandle;
+  Status = AcpiSdt->GetChild (INTxPkgHandle, &MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (MemberHandle != NULL);
+
+  if (PreviousHandle != NULL) {
+    Status = AcpiSdt->Close (PreviousHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  Status = AcpiSdt->GetOption (MemberHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+
+  //
+  // Skip byte prefix
+  //
+  Data += 1;
+
+  if (*Data != SxNum) {
+
+    *Data = SxNum;
+  }
+
+  Status = AcpiSdt->Close (MemberHandle);
+  ASSERT_EFI_ERROR (Status);
+
+}
+
+/**
+  Check the name package belonged to PRW
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param PrwPkgHandle     ACPI PRW package handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+VOID
+SdtCheckNamePackage (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        PrwPkgHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_ACPI_HANDLE    InPkgHandle;
+  EFI_STATUS         Status;
+  EFI_ACPI_DATA_TYPE DataType;
+  UINT8              *Data;
+  UINTN              DataSize;
+
+  Status = AcpiSdt->GetOption (PrwPkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);
+  ASSERT (*Data == AML_NAME_OP);
+
+  Status = AcpiSdt->GetOption (PrwPkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD);
+
+  //
+  // Get the inside package handle
+  //
+  InPkgHandle = NULL;
+  Status = AcpiSdt->Open (Data, &InPkgHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // update the package in name op for wakeup info
+  //
+  if ((PciDeviceInfo->GPEPin != 0xFF) && (PciDeviceInfo->SxNum != 0xFF))
+    SdtUpdatePackageInName (AcpiSdt, InPkgHandle, PciDeviceInfo->GPEPin, PciDeviceInfo->SxNum);
+
+  Status = AcpiSdt->Close (InPkgHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  return;
+
+}
+
+/**
+  update wakeup info inside the PRW method for the given pci device handle
+
+  @param AcpiSdt       Pointer to Acpi SDT protocol
+  @param PciHandle     ACPI pci device handle
+  @param PciDeviceInfo Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePrwPackage (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        PciHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    PrwPkgHandle;
+
+  //
+  // Find the PRT method under this pci device
+  //
+  PrwPkgHandle = NULL;
+  Status = AcpiSdt->FindPath (PciHandle, "_PRW", &PrwPkgHandle);
+
+  if (EFI_ERROR (Status)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PrwPkgHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SdtCheckNamePackage(AcpiSdt, PrwPkgHandle, PciDeviceInfo);
+
+  Status = AcpiSdt->Close (PrwPkgHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  update pci routing information in acpi table based on pcd settings
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param PciRootHandle       ACPI root bridge handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePciRouting (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        PciRootHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    PciBridgeHandle;
+  UINT32             PciAddress;
+
+
+  PciBridgeHandle = NULL;
+  if (PciDeviceInfo->BridgeAddress == 0x00000000) {
+    //
+    // Its bridge is the host root bridge
+    //
+    PciBridgeHandle = PciRootHandle;
+
+  } else {
+
+    //
+    // Its bridge is just a pci device under the host bridge
+    //
+
+    //
+    // Conver the bridge address into one that acpi table can recognize
+    //
+    PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
+
+    //
+    // Scan the whole table to find the pci device
+    //
+    PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
+    if (PciBridgeHandle == NULL) {
+
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  Status = SdtUpdatePrtMethod(AcpiSdt, PciBridgeHandle, PciDeviceInfo);
+
+  if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+    Status = AcpiSdt->Close (PciBridgeHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+
+/**
+  update power resource wake up information in acpi table based on pcd settings
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param PciRootHandle    ACPI root bridge handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePowerWake (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        PciRootHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  )
+{
+  EFI_STATUS         Status;
+  EFI_ACPI_HANDLE    PciBridgeHandle;
+  EFI_ACPI_HANDLE    PciDeviceHandle;
+  UINT32             PciAddress;
+
+  PciBridgeHandle = NULL;
+  if (PciDeviceInfo->BridgeAddress == 0x00000000) {
+    //
+    // Its bridge is the host root bridge
+    //
+    PciBridgeHandle = PciRootHandle;
+
+  } else {
+
+    //
+    // Its bridge is just a pci device under the host bridge
+    //
+
+    //
+    // Conver the bridge address into one that acpi table can recognize
+    //
+    PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->BridgeAddress);
+
+    //
+    // Scan the whole table to find the pci device
+    //
+    PciBridgeHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciRootHandle, SdtFindPciDeviceHandle, &PciAddress);
+
+    if (PciBridgeHandle == NULL) {
+
+      Status = AcpiSdt->Close (PciRootHandle);
+      ASSERT_EFI_ERROR (Status);
+
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  PciDeviceHandle = NULL;
+
+  //
+  // Conver the device address into one that acpi table can recognize
+  //
+  PciAddress = SdtConvertToAcpiPciAdress (PciDeviceInfo->DeviceAddress);
+
+  //
+  // Scan the whole table to find the pci device
+  //
+  PciDeviceHandle = SdtGetHandleByScanAllChilds(AcpiSdt, PciBridgeHandle, SdtFindPciDeviceHandle, &PciAddress);
+
+  if (PciDeviceHandle == NULL) {
+    if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+      Status = AcpiSdt->Close (PciBridgeHandle);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = SdtUpdatePrwPackage(AcpiSdt, PciDeviceHandle, PciDeviceInfo);
+
+  Status = AcpiSdt->Close (PciDeviceHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  if (PciDeviceInfo->BridgeAddress != 0x00000000) {
+    Status = AcpiSdt->Close (PciBridgeHandle);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+
+/**
+  Get the root bridge handle by scanning the acpi table
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param DsdtHandle       ACPI root handle
+
+  @retval EFI_ACPI_HANDLE the handle of the root bridge
+**/
+EFI_ACPI_HANDLE
+SdtGetRootBridgeHandle (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        DsdtHandle
+  )
+{
+  EFI_ACPI_HANDLE    PciRootHandle;
+
+  //
+  // Scan the whole table to find the root bridge
+  //
+  PciRootHandle = NULL;
+  PciRootHandle = SdtGetHandleByScanAllChilds(AcpiSdt, DsdtHandle, SdtFindRootBridgeHandle, NULL);
+  ASSERT (PciRootHandle != NULL);
+
+  return PciRootHandle;
+}
+
+
+/**
+  Check input Pci device info is changed from the default values
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+  @param UpdatePRT        Pointer to BOOLEAN
+  @param UpdatePRW        Pointer to BOOLEAN
+
+**/
+VOID
+SdtCheckPciDeviceInfoChanged (
+  IN PCI_DEVICE_INFO        *PciDeviceInfo,
+  IN BOOLEAN                *UpdatePRT,
+  IN BOOLEAN                *UpdatePRW
+  )
+{
+  UINTN Index = 0;
+
+  if (mQNCPciInfo == NULL) {
+    *UpdatePRT = FALSE;
+    *UpdatePRW = FALSE;
+    return;
+  }
+
+  *UpdatePRT = TRUE;
+  *UpdatePRW = TRUE;
+
+  for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {
+    if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)
+      && (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {
+      //
+      // Find one matched entry
+      //
+      if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {
+        *UpdatePRT = FALSE;
+        *UpdatePRW = FALSE;
+        //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
+      } else {
+        if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)
+          *UpdatePRT = FALSE;
+
+        if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)
+          *UpdatePRW = FALSE;
+
+        if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFFULL)
+          *UpdatePRT = FALSE;
+
+        if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)
+          *UpdatePRW = FALSE;
+
+        //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
+      }
+      break;
+    }
+  }
+
+  //if (Index == 42) {
+  //  DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));
+  //}
+
+  return;
+}

+ 316 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPciUpdate.h

@@ -0,0 +1,316 @@
+/** @file
+Update the _PRT and _PRW method for pci devices
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#ifndef _ACPI_PCI_UPDATE_H_
+#define _ACPI_PCI_UPDATE_H_
+
+
+//
+// Primary OpCode
+//
+#define AML_ZERO_OP                  0x00
+#define AML_ONE_OP                   0x01
+#define AML_ALIAS_OP                 0x06
+#define AML_NAME_OP                  0x08
+#define AML_BYTE_PREFIX              0x0a
+#define AML_WORD_PREFIX              0x0b
+#define AML_DWORD_PREFIX             0x0c
+#define AML_STRING_PREFIX            0x0d
+#define AML_QWORD_PREFIX             0x0e
+#define AML_SCOPE_OP                 0x10
+#define AML_BUFFER_OP                0x11
+#define AML_PACKAGE_OP               0x12
+#define AML_VAR_PACKAGE_OP           0x13
+#define AML_METHOD_OP                0x14
+#define AML_DUAL_NAME_PREFIX         0x2e
+#define AML_MULTI_NAME_PREFIX        0x2f
+#define AML_NAME_CHAR_A              0x41
+#define AML_NAME_CHAR_B              0x42
+#define AML_NAME_CHAR_C              0x43
+#define AML_NAME_CHAR_D              0x44
+#define AML_NAME_CHAR_E              0x45
+#define AML_NAME_CHAR_F              0x46
+#define AML_NAME_CHAR_G              0x47
+#define AML_NAME_CHAR_H              0x48
+#define AML_NAME_CHAR_I              0x49
+#define AML_NAME_CHAR_J              0x4a
+#define AML_NAME_CHAR_K              0x4b
+#define AML_NAME_CHAR_L              0x4c
+#define AML_NAME_CHAR_M              0x4d
+#define AML_NAME_CHAR_N              0x4e
+#define AML_NAME_CHAR_O              0x4f
+#define AML_NAME_CHAR_P              0x50
+#define AML_NAME_CHAR_Q              0x51
+#define AML_NAME_CHAR_R              0x52
+#define AML_NAME_CHAR_S              0x53
+#define AML_NAME_CHAR_T              0x54
+#define AML_NAME_CHAR_U              0x55
+#define AML_NAME_CHAR_V              0x56
+#define AML_NAME_CHAR_W              0x57
+#define AML_NAME_CHAR_X              0x58
+#define AML_NAME_CHAR_Y              0x59
+#define AML_NAME_CHAR_Z              0x5a
+#define AML_ROOT_CHAR                0x5c
+#define AML_PARENT_PREFIX_CHAR       0x5e
+#define AML_NAME_CHAR__              0x5f
+#define AML_LOCAL0                   0x60
+#define AML_LOCAL1                   0x61
+#define AML_LOCAL2                   0x62
+#define AML_LOCAL3                   0x63
+#define AML_LOCAL4                   0x64
+#define AML_LOCAL5                   0x65
+#define AML_LOCAL6                   0x66
+#define AML_LOCAL7                   0x67
+#define AML_ARG0                     0x68
+#define AML_ARG1                     0x69
+#define AML_ARG2                     0x6a
+#define AML_ARG3                     0x6b
+#define AML_ARG4                     0x6c
+#define AML_ARG5                     0x6d
+#define AML_ARG6                     0x6e
+#define AML_STORE_OP                 0x70
+#define AML_REF_OF_OP                0x71
+#define AML_ADD_OP                   0x72
+#define AML_CONCAT_OP                0x73
+#define AML_SUBTRACT_OP              0x74
+#define AML_INCREMENT_OP             0x75
+#define AML_DECREMENT_OP             0x76
+#define AML_MULTIPLY_OP              0x77
+#define AML_DIVIDE_OP                0x78
+#define AML_SHIFT_LEFT_OP            0x79
+#define AML_SHIFT_RIGHT_OP           0x7a
+#define AML_AND_OP                   0x7b
+#define AML_NAND_OP                  0x7c
+#define AML_OR_OP                    0x7d
+#define AML_NOR_OP                   0x7e
+#define AML_XOR_OP                   0x7f
+#define AML_NOT_OP                   0x80
+#define AML_FIND_SET_LEFT_BIT_OP     0x81
+#define AML_FIND_SET_RIGHT_BIT_OP    0x82
+#define AML_DEREF_OF_OP              0x83
+#define AML_CONCAT_RES_OP            0x84
+#define AML_MOD_OP                   0x85
+#define AML_NOTIFY_OP                0x86
+#define AML_SIZE_OF_OP               0x87
+#define AML_INDEX_OP                 0x88
+#define AML_MATCH_OP                 0x89
+#define AML_CREATE_DWORD_FIELD_OP    0x8a
+#define AML_CREATE_WORD_FIELD_OP     0x8b
+#define AML_CREATE_BYTE_FIELD_OP     0x8c
+#define AML_CREATE_BIT_FIELD_OP      0x8d
+#define AML_OBJECT_TYPE_OP           0x8e
+#define AML_CREATE_QWORD_FIELD_OP    0x8f
+#define AML_LAND_OP                  0x90
+#define AML_LOR_OP                   0x91
+#define AML_LNOT_OP                  0x92
+#define AML_LEQUAL_OP                0x93
+#define AML_LGREATER_OP              0x94
+#define AML_LLESS_OP                 0x95
+#define AML_TO_BUFFER_OP             0x96
+#define AML_TO_DEC_STRING_OP         0x97
+#define AML_TO_HEX_STRING_OP         0x98
+#define AML_TO_INTEGER_OP            0x99
+#define AML_TO_STRING_OP             0x9c
+#define AML_COPY_OBJECT_OP           0x9d
+#define AML_MID_OP                   0x9e
+#define AML_CONTINUE_OP              0x9f
+#define AML_IF_OP                    0xa0
+#define AML_ELSE_OP                  0xa1
+#define AML_WHILE_OP                 0xa2
+#define AML_NOOP_OP                  0xa3
+#define AML_RETURN_OP                0xa4
+#define AML_BREAK_OP                 0xa5
+#define AML_BREAK_POINT_OP           0xcc
+#define AML_ONES_OP                  0xff
+
+//
+// Extended OpCode
+//
+#define AML_EXT_OP                   0x5b
+
+#define AML_EXT_MUTEX_OP             0x01
+#define AML_EXT_EVENT_OP             0x02
+#define AML_EXT_COND_REF_OF_OP       0x12
+#define AML_EXT_CREATE_FIELD_OP      0x13
+#define AML_EXT_LOAD_TABLE_OP        0x1f
+#define AML_EXT_LOAD_OP              0x20
+#define AML_EXT_STALL_OP             0x21
+#define AML_EXT_SLEEP_OP             0x22
+#define AML_EXT_ACQUIRE_OP           0x23
+#define AML_EXT_SIGNAL_OP            0x24
+#define AML_EXT_WAIT_OP              0x25
+#define AML_EXT_RESET_OP             0x26
+#define AML_EXT_RELEASE_OP           0x27
+#define AML_EXT_FROM_BCD_OP          0x28
+#define AML_EXT_TO_BCD_OP            0x29
+#define AML_EXT_UNLOAD_OP            0x2a
+#define AML_EXT_REVISION_OP          0x30
+#define AML_EXT_DEBUG_OP             0x31
+#define AML_EXT_FATAL_OP             0x32
+#define AML_EXT_TIMER_OP             0x33
+#define AML_EXT_REGION_OP            0x80
+#define AML_EXT_FIELD_OP             0x81
+#define AML_EXT_DEVICE_OP            0x82
+#define AML_EXT_PROCESSOR_OP         0x83
+#define AML_EXT_POWER_RES_OP         0x84
+#define AML_EXT_THERMAL_ZONE_OP      0x85
+#define AML_EXT_INDEX_FIELD_OP       0x86
+#define AML_EXT_BANK_FIELD_OP        0x87
+#define AML_EXT_DATA_REGION_OP       0x88
+
+#pragma pack(1)
+
+typedef struct {
+  UINT32    BridgeAddress;
+  UINT32    DeviceAddress;
+  UINT8     INTA[2];    // the first member record the 8259 link, the second member record the io apic irq number
+  UINT8     INTB[2];
+  UINT8     INTC[2];
+  UINT8     INTD[2];
+
+  UINT8     GPEPin;
+  UINT8     SxNum;
+} PCI_DEVICE_INFO;
+
+#pragma pack()
+
+#define PCI_DEVICE_INFO_MAX_NUM  50
+#define CURRENT_PCI_DEVICE_NUM   13
+
+#define  PIRQ_LINKA       1
+#define  PIRQ_LINKB       2
+#define  PIRQ_LINKC       3
+#define  PIRQ_LINKD       4
+#define  PIRQ_LINKE       5
+#define  PIRQ_LINKF       6
+#define  PIRQ_LINKG       7
+#define  PIRQ_LINKH       8
+#define  PIRQ_INVALID  0xFF
+
+typedef struct _PCI_DEVICE_SETTING{
+  UINT8    PciDeviceInfoNumber;
+  PCI_DEVICE_INFO PciDeviceInfo[PCI_DEVICE_INFO_MAX_NUM];
+}PCI_DEVICE_SETTING;
+
+typedef struct _AML_BYTE_ENCODING AML_BYTE_ENCODING;
+
+//
+// AML Handle Entry definition.
+//
+//  Signature must be set to EFI_AML_HANDLE_SIGNATURE or EFI_AML_ROOT_HANDLE_SIGNATURE
+//  Buffer is the ACPI node buffer pointer, the first/second bytes are opcode.
+//         This buffer should not be freed.
+//  Size is the total size of this ACPI node buffer.
+//
+typedef struct {
+  UINT32                  Signature;
+  UINT8                   *Buffer;
+  UINTN                   Size;
+  AML_BYTE_ENCODING       *AmlByteEncoding;
+  BOOLEAN                 Modified;
+} EFI_AML_HANDLE;
+
+typedef UINT32 AML_OP_PARSE_INDEX;
+
+typedef UINT32 AML_OP_PARSE_FORMAT;
+
+typedef UINT32 AML_OP_ATTRIBUTE;
+
+struct _AML_BYTE_ENCODING {
+  UINT8                      OpCode;
+  UINT8                      SubOpCode;
+  AML_OP_PARSE_INDEX         MaxIndex;
+  AML_OP_PARSE_FORMAT        Format[6];
+  AML_OP_ATTRIBUTE           Attribute;
+};
+
+
+//
+// Check device info fucntion prototype
+//
+typedef
+BOOLEAN
+(* CHECK_HANDLE_INFO) (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        CheckHandle,
+  IN VOID                   *Context
+  );
+
+extern EFI_ACPI_HANDLE mDsdtHandle;
+extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
+
+/**
+  Init Pci Device Structure
+
+  @param mConfigData    - Pointer of Pci Device information Structure
+
+**/
+VOID
+InitPciDeviceInfoStructure (
+  PCI_DEVICE_SETTING            *mConfigData
+  );
+/**
+  update pci routing information in acpi table based on pcd settings
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param DsdtHandle       ACPI root handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePciRouting (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        DsdtHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  );
+
+
+/**
+  update power resource wake up information in acpi table based on pcd settings
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param DsdtHandle       ACPI root handle
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+
+**/
+EFI_STATUS
+SdtUpdatePowerWake (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        DsdtHandle,
+  IN PCI_DEVICE_INFO        *PciDeviceInfo
+  );
+
+/**
+  Get the root bridge handle by scanning the acpi table
+
+  @param AcpiSdt          Pointer to Acpi SDT protocol
+  @param DsdtHandle       ACPI root handle
+
+  @retval EFI_ACPI_HANDLE the handle of the root bridge
+**/
+EFI_ACPI_HANDLE
+SdtGetRootBridgeHandle (
+  IN EFI_ACPI_SDT_PROTOCOL  *AcpiSdt,
+  IN EFI_ACPI_HANDLE        DsdtHandle
+  );
+
+/**
+  Check input Pci device info is changed from the default values
+  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
+  @param UpdatePRT        Pointer to BOOLEAN
+  @param UpdatePRW        Pointer to BOOLEAN
+
+**/
+VOID
+SdtCheckPciDeviceInfoChanged (
+  IN PCI_DEVICE_INFO        *PciDeviceInfo,
+  IN BOOLEAN                *UpdatePRT,
+  IN BOOLEAN                *UpdatePRW
+  );
+#endif

+ 805 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c

@@ -0,0 +1,805 @@
+/** @file
+ACPI Platform Driver
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Protocol/AcpiTable.h>
+#include <IndustryStandard/Pci22.h>
+#include "AcpiPlatform.h"
+
+//
+// Global Variable
+//
+EFI_GLOBAL_NVS_AREA_PROTOCOL  mGlobalNvsArea;
+EFI_ACPI_SDT_PROTOCOL         *mAcpiSdt;
+
+EFI_ACPI_HANDLE mDsdtHandle = NULL;
+
+
+EFI_STATUS
+LocateSupportProtocol (
+  IN  EFI_GUID                       *Protocol,
+  OUT VOID                           **Instance,
+  IN  UINT32                         Type
+  )
+/*++
+
+Routine Description:
+
+  Locate the first instance of a protocol.  If the protocol requested is an
+  FV protocol, then it will return the first FV that contains the ACPI table
+  storage file.
+
+Arguments:
+
+  Protocol      The protocol to find.
+  Instance      Return pointer to the first instance of the protocol
+
+Returns:
+
+  EFI_SUCCESS           The function completed successfully.
+  EFI_NOT_FOUND         The protocol could not be located.
+  EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
+
+--*/
+{
+  EFI_STATUS              Status;
+  EFI_HANDLE              *HandleBuffer;
+  UINTN                   NumberOfHandles;
+  EFI_FV_FILETYPE         FileType;
+  UINT32                  FvStatus;
+  EFI_FV_FILE_ATTRIBUTES  Attributes;
+  UINTN                   Size;
+  UINTN                   i;
+
+  FvStatus = 0;
+
+  //
+  // Locate protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   Protocol,
+                   NULL,
+                   &NumberOfHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status)) {
+
+    //
+    // Defined errors at this time are not found and out of resources.
+    //
+    return Status;
+  }
+
+
+
+  //
+  // Looking for FV with ACPI storage file
+  //
+
+  for (i = 0; i < NumberOfHandles; i++) {
+    //
+    // Get the protocol on this handle
+    // This should not fail because of LocateHandleBuffer
+    //
+    Status = gBS->HandleProtocol (
+                     HandleBuffer[i],
+                     Protocol,
+                     Instance
+                     );
+    ASSERT_EFI_ERROR (Status);
+
+    if (!Type) {
+      //
+      // Not looking for the FV protocol, so find the first instance of the
+      // protocol.  There should not be any errors because our handle buffer
+      // should always contain at least one or LocateHandleBuffer would have
+      // returned not found.
+      //
+      break;
+    }
+
+    //
+    // See if it has the ACPI storage file
+    //
+
+    Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
+                                                              (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+                                                              NULL,
+                                                              &Size,
+                                                              &FileType,
+                                                              &Attributes,
+                                                              &FvStatus
+                                                              );
+
+    //
+    // If we found it, then we are done
+    //
+    if (Status == EFI_SUCCESS) {
+      break;
+    }
+  }
+
+  //
+  // Our exit status is determined by the success of the previous operations
+  // If the protocol was found, Instance already points to it.
+  //
+
+  //
+  // Free any allocated buffers
+  //
+  gBS->FreePool (HandleBuffer);
+
+  return Status;
+}
+
+
+VOID
+DsdtTableUpdate (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
+  IN OUT   EFI_ACPI_TABLE_VERSION       *Version
+  )
+/*++
+
+  Routine Description:
+
+    Update the DSDT table
+
+  Arguments:
+
+    Table   - The table to be set
+    Version - Version to publish
+
+  Returns:
+
+    None
+
+--*/
+{
+
+  UINT8      *CurrPtr;
+  UINT8      *DsdtPointer;
+  UINT32     *Signature;
+  UINT8      *Operation;
+  UINT32     *Address;
+  UINT16     *Size;
+  //
+  // Loop through the ASL looking for values that we must fix up.
+  //
+  CurrPtr = (UINT8 *) TableHeader;
+  for (DsdtPointer = CurrPtr;
+       DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+       DsdtPointer++
+      )
+  {
+    Signature = (UINT32 *) DsdtPointer;
+    switch (*Signature) {
+    //
+    // MNVS operation region
+    //
+    case (SIGNATURE_32 ('M', 'N', 'V', 'S')):
+      //
+      // Conditional match.  For Region Objects, the Operator will always be the
+      // byte immediately before the specific name.  Therefore, subtract 1 to check
+      // the Operator.
+      //
+      Operation = DsdtPointer - 1;
+      if (*Operation == AML_OPREGION_OP) {
+        Address   = (UINT32 *) (DsdtPointer + 6);
+        *Address  = (UINT32) (UINTN) mGlobalNvsArea.Area;
+        Size      = (UINT16 *) (DsdtPointer + 11);
+        *Size     = sizeof (EFI_GLOBAL_NVS_AREA);
+      }
+      break;
+
+    //
+    // Update processor PBLK register I/O base address
+    //
+    case (SIGNATURE_32 ('P', 'R', 'I', 'O')):
+      //
+      // Conditional match. Update the following ASL code:
+      // Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
+      // The 3rd parameter will be updated to the actual PBLK I/O base address.
+      // the Operator.
+      //
+      Operation = DsdtPointer - 8;
+      if ((*Operation == AML_EXT_OP) && (*(Operation + 1) == AML_EXT_PROCESSOR_OP)) {
+        *(UINT32 *)DsdtPointer = PcdGet16(PcdPmbaIoBaseAddress);
+      }
+      break;
+    default:
+      break;
+    }
+  }
+}
+
+
+VOID
+ApicTableUpdate (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
+  IN OUT   EFI_ACPI_TABLE_VERSION       *Version
+  )
+/*++
+
+  Routine Description:
+
+    Update the processors information in the APIC table
+
+  Arguments:
+
+    Table   - The table to be set
+    Version - Version to publish
+
+  Returns:
+
+    None
+
+--*/
+{
+  EFI_STATUS                 Status;
+  EFI_MP_SERVICES_PROTOCOL   *MpService;
+  UINT8                      *CurrPtr;
+  UINT8                      *EndPtr;
+  UINT8                      CurrIoApic;
+  UINT8                      CurrProcessor;
+  UINTN                      NumberOfCPUs;
+  UINTN                      NumberOfEnabledCPUs;
+  EFI_PROCESSOR_INFORMATION  MpContext;
+  ACPI_APIC_STRUCTURE_PTR    *ApicPtr;
+
+  CurrIoApic    = 0;
+  CurrProcessor = 0;
+  //
+  // Find the MP Protocol. This is an MP platform, so MP protocol must be
+  // there.
+  //
+  Status = gBS->LocateProtocol (
+                   &gEfiMpServiceProtocolGuid,
+                   NULL,
+                  (VOID**)&MpService
+                   );
+  if (EFI_ERROR (Status)) {
+    //
+    // Failed to get MP information, doesn't publish the invalid table
+    //
+    *Version = EFI_ACPI_TABLE_VERSION_NONE;
+    return;
+  }
+
+  //
+  // Determine the number of processors
+  //
+  MpService->GetNumberOfProcessors (
+              MpService,
+              &NumberOfCPUs,
+              &NumberOfEnabledCPUs
+              );
+
+  CurrPtr = (UINT8*) &(TableHeader[1]);
+  CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
+  EndPtr  = (UINT8*) TableHeader;
+  EndPtr  = EndPtr + TableHeader->Length;
+
+  while (CurrPtr < EndPtr) {
+
+    ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
+    switch (ApicPtr->AcpiApicCommon.Type) {
+
+      case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
+        ApicPtr->AcpiLocalApic.Flags = 0;
+        ApicPtr->AcpiLocalApic.ApicId = 0;
+        Status = MpService->GetProcessorInfo (
+                              MpService,
+                              CurrProcessor,
+                              &MpContext
+                              );
+
+        if (!EFI_ERROR (Status)) {
+          if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
+            ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
+          }
+          ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
+        }
+        CurrProcessor++;
+        break;
+
+      case EFI_ACPI_1_0_IO_APIC:
+        //
+        // IO APIC entries can be patched here
+        //
+        if (CurrIoApic == 0) {
+          //
+          // Update SOC internel IOAPIC base
+          //
+          ApicPtr->AcpiIoApic.IoApicId      =  PcdGet8 (PcdIoApicSettingIoApicId);
+          ApicPtr->AcpiIoApic.IoApicAddress =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
+          ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
+        } else {
+          //
+          // Porting is required to update other IOAPIC entries if available
+          //
+          ASSERT (0);
+        }
+        CurrIoApic++;
+        break;
+
+      default:
+        break;
+      };
+    CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
+  }
+}
+
+VOID
+AcpiUpdateTable (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
+  IN OUT   EFI_ACPI_TABLE_VERSION       *Version
+  )
+/*++
+
+  Routine Description:
+
+    Set the correct table revision upon the setup value
+
+  Arguments:
+
+    Table   - The table to be set
+    Version - Version to publish
+
+  Returns:
+
+    None
+
+--*/
+
+{
+  EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader1;
+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader2;
+  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader3;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *AllocationStructurePtr;
+
+  if (TableHeader != NULL && Version != NULL) {
+
+    *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+    //
+    // Here we use all 3.0 signature because all version use same signature if they supported
+    //
+    switch (TableHeader->Signature) {
+    //
+    // "APIC" Multiple APIC Description Table
+    //
+    case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+      ApicTableUpdate (TableHeader, Version);
+      break;
+    //
+    // "DSDT" Differentiated System Description Table
+    //
+    case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+      DsdtTableUpdate (TableHeader, Version);
+      break;
+
+    //
+    // "FACP" Fixed ACPI Description Table (FADT)
+    //
+    case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+      *Version = EFI_ACPI_TABLE_VERSION_NONE;
+      if (TableHeader->Revision == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+        *Version = EFI_ACPI_TABLE_VERSION_1_0B;
+        FadtHeader1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+        FadtHeader1->SmiCmd     = PcdGet16(PcdSmmActivationPort);
+        FadtHeader1->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+        FadtHeader1->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+        FadtHeader1->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+        FadtHeader1->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
+      } else if (TableHeader->Revision == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+        *Version = EFI_ACPI_TABLE_VERSION_2_0;
+        FadtHeader2 = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+        FadtHeader2->SmiCmd     = PcdGet16(PcdSmmActivationPort);
+        FadtHeader2->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+        FadtHeader2->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+        FadtHeader2->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+        FadtHeader2->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
+        FadtHeader2->XPm1aEvtBlk.Address = FadtHeader2->Pm1aEvtBlk;
+        FadtHeader2->XPm1aCntBlk.Address = FadtHeader2->Pm1aCntBlk;
+        FadtHeader2->XPmTmrBlk.Address   = FadtHeader2->PmTmrBlk;
+        FadtHeader2->XGpe0Blk.Address    = FadtHeader2->Gpe0Blk;
+      } else if (TableHeader->Revision == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+        *Version = EFI_ACPI_TABLE_VERSION_3_0;
+        FadtHeader3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
+        FadtHeader3->SmiCmd     = PcdGet16(PcdSmmActivationPort);
+        FadtHeader3->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
+        FadtHeader3->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
+        FadtHeader3->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
+        FadtHeader3->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
+        FadtHeader3->XPm1aEvtBlk.Address = FadtHeader3->Pm1aEvtBlk;
+        FadtHeader3->XPm1aCntBlk.Address = FadtHeader3->Pm1aCntBlk;
+        FadtHeader3->XPmTmrBlk.Address   = FadtHeader3->PmTmrBlk;
+        FadtHeader3->XGpe0Blk.Address    = FadtHeader3->Gpe0Blk;
+      }
+      break;
+    //
+    // "FACS" Firmware ACPI Control Structure
+    //
+    case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
+      break;
+    //
+    // "SSDT" Secondary System Description Table
+    //
+    case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+    break;
+    //
+    // "HPET" IA-PC High Precision Event Timer Table
+    //
+    case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+      //
+      // If HPET is disabled in setup, don't publish the table.
+      //
+      if (mGlobalNvsArea.Area->HpetEnable == 0) {
+        *Version = EFI_ACPI_TABLE_VERSION_NONE;
+      }
+      ((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) TableHeader)->BaseAddressLower32Bit.Address
+        = PcdGet64 (PcdHpetBaseAddress);
+      break;
+    //
+    // "SPCR" Serial Port Concole Redirection Table
+    //
+    case EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
+      break;
+    //
+    // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
+    //
+    case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+      AllocationStructurePtr = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)
+        ((UINT8 *)TableHeader + sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER));
+      AllocationStructurePtr->BaseAddress = PcdGet64(PcdPciExpressBaseAddress);
+      break;
+    // Lakeport platform doesn't support the following table
+    /*
+      //
+    // "ECDT" Embedded Controller Boot Resources Table
+        //
+    case EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE:
+      break;
+        //
+    // "PSDT" Persistent System Description Table
+          //
+    case EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+      break;
+          //
+    // "SBST" Smart Battery Specification Table
+    //
+    case EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE:
+          break;
+    //
+    // "SLIT" System Locality Information Table
+    //
+    case EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
+          break;
+    //
+    // "SRAT" Static Resource Affinity Table
+    //
+    case EFI_ACPI_3_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE:
+    break;
+  //
+    // "XSDT" Extended System Description Table
+  //
+    case EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+      break;
+  //
+    // "BOOT" MS Simple Boot Spec
+  //
+    case EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE:
+      break;
+  //
+    // "CPEP" Corrected Platform Error Polling Table
+  //
+    case EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE:
+      break;
+  //
+    // "DBGP" MS Debug Port Spec
+  //
+    case EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE:
+      break;
+    //
+    // "ETDT" Event Timer Description Table
+    //
+    case EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE:
+      break;
+    //
+    // "SPMI" Server Platform Management Interface Table
+    //
+    case EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE:
+      break;
+    //
+    // "TCPA" Trusted Computing Platform Alliance Capabilities Table
+    //
+    case EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE:
+      break;
+    */
+    default:
+      break;
+    }
+  }
+}
+
+//
+// Description:
+//    Entrypoint of Acpi Platform driver
+// In:
+//    ImageHandle
+//    SystemTable
+// Out:
+//    EFI_SUCCESS
+//    EFI_LOAD_ERROR
+//    EFI_OUT_OF_RESOURCES
+//
+
+EFI_STATUS
+AcpiPlatformEntryPoint (
+  IN EFI_HANDLE     ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_ACPI_TABLE_PROTOCOL       *AcpiTable;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+  INTN                          Instance;
+  EFI_ACPI_COMMON_HEADER        *CurrentTable;
+  UINTN                         TableHandle;
+  UINT32                        FvStatus;
+  UINTN                         Size;
+  EFI_ACPI_TABLE_VERSION        Version;
+  EFI_HANDLE                    Handle;
+  UINTN                         Index;
+  PCI_DEVICE_INFO               *PciDeviceInfo;
+  EFI_ACPI_HANDLE               PciRootHandle;
+  BOOLEAN                       UpdatePRT;
+  BOOLEAN                       UpdatePRW;
+  PCI_DEVICE_SETTING            *mConfigData;
+
+  DEBUG((DEBUG_INFO, "ACPI Platform start...\n"));
+
+  Instance = 0;
+  TableHandle = 0;
+  CurrentTable = NULL;
+  mConfigData  = NULL;
+
+  //
+  // Initialize the EFI Driver Library
+  //
+
+  ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512);
+
+  Status = gBS->AllocatePool (
+                   EfiACPIMemoryNVS,
+                   sizeof (EFI_GLOBAL_NVS_AREA),
+                   (VOID**)&mGlobalNvsArea.Area
+                   );
+
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &Handle,
+                  &gEfiGlobalNvsAreaProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mGlobalNvsArea
+                  );
+
+  ASSERT_EFI_ERROR (Status);
+  if (!EFI_ERROR (Status)) {
+    SetMem (
+      mGlobalNvsArea.Area,
+      sizeof (EFI_GLOBAL_NVS_AREA),
+      0
+      );
+  }
+
+  //
+  // Initialize the data.  Eventually, this will be controlled by setup options.
+  //
+  mGlobalNvsArea.Area->HpetEnable           =  PcdGetBool (PcdHpetEnable);
+  mGlobalNvsArea.Area->Pm1blkIoBaseAddress  =  PcdGet16(PcdPm1blkIoBaseAddress);
+  mGlobalNvsArea.Area->PmbaIoBaseAddress    =  PcdGet16(PcdPmbaIoBaseAddress);
+  mGlobalNvsArea.Area->Gpe0blkIoBaseAddress =  PcdGet16(PcdGpe0blkIoBaseAddress);
+  mGlobalNvsArea.Area->GbaIoBaseAddress     =  PcdGet16(PcdGbaIoBaseAddress);
+  mGlobalNvsArea.Area->SmbaIoBaseAddress    =  PcdGet16(PcdSmbaIoBaseAddress);
+  mGlobalNvsArea.Area->WdtbaIoBaseAddress   =  PcdGet16(PcdWdtbaIoBaseAddress);
+  mGlobalNvsArea.Area->HpetBaseAddress      =  (UINT32)PcdGet64(PcdHpetBaseAddress);
+  mGlobalNvsArea.Area->HpetSize             =  (UINT32)PcdGet64(PcdHpetSize);
+  mGlobalNvsArea.Area->PciExpressBaseAddress=  (UINT32)PcdGet64(PcdPciExpressBaseAddress);
+  mGlobalNvsArea.Area->PciExpressSize       =  (UINT32)PcdGet64(PcdPciExpressSize);
+  mGlobalNvsArea.Area->RcbaMmioBaseAddress  =  (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
+  mGlobalNvsArea.Area->RcbaMmioSize         =  (UINT32)PcdGet64(PcdRcbaMmioSize);
+  mGlobalNvsArea.Area->IoApicBaseAddress    =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
+  mGlobalNvsArea.Area->IoApicSize           =  (UINT32)PcdGet64(PcdIoApicSize);
+  mGlobalNvsArea.Area->TpmPresent           =  (UINT32)(FALSE);
+  mGlobalNvsArea.Area->DBG2Present          =  (UINT32)(FALSE);
+  mGlobalNvsArea.Area->PlatformType         =  (UINT32)PcdGet16 (PcdPlatformType);
+
+  //
+  // Configure platform IO expander I2C Slave Address.
+  //
+  if (mGlobalNvsArea.Area->PlatformType == Galileo) {
+    if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
+      mGlobalNvsArea.Area->AlternateSla = FALSE;
+    } else {
+      mGlobalNvsArea.Area->AlternateSla = TRUE;
+    }
+  }
+
+  //
+  // Find the AcpiTable protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
+  if (EFI_ERROR (Status)) {
+    return EFI_ABORTED;
+  }
+
+  //
+  // Initialize MADT table
+  //
+  Status = MadtTableInitialize (&CurrentTable, &Size);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Perform any table specific updates.
+  //
+  AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
+
+  //
+  // Update the check sum
+  // It needs to be zeroed before the checksum calculation
+  //
+  ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+  ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
+    CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+  //
+  // Add the table
+  //
+  TableHandle = 0;
+  Status = AcpiTable->InstallAcpiTable (
+                            AcpiTable,
+                            CurrentTable,
+                            CurrentTable->Length,
+                          &TableHandle
+                          );
+  ASSERT_EFI_ERROR (Status);
+  CurrentTable = NULL;
+
+  //
+  // Init Pci Device PRT PRW information structure from PCD
+  //
+  mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING));
+  ASSERT (mConfigData != NULL);
+  InitPciDeviceInfoStructure (mConfigData);
+  //
+  // Get the Acpi SDT protocol for manipulation on acpi table
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Locate the firmware volume protocol
+  //
+  Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
+  if (EFI_ERROR (Status)) {
+    return EFI_ABORTED;
+  }
+  //
+  // Read tables from the storage file.
+  //
+
+  while (Status == EFI_SUCCESS) {
+
+    Status = FwVol->ReadSection (
+                      FwVol,
+                      (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+                      EFI_SECTION_RAW,
+                      Instance,
+                      (VOID**)&CurrentTable,
+                      &Size,
+                      &FvStatus
+                      );
+
+    if (!EFI_ERROR(Status)) {
+      //
+      // Perform any table specific updates.
+      //
+      AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
+
+      //
+      // Update the check sum
+      // It needs to be zeroed before the checksum calculation
+      //
+      ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+      ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
+        CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+      //
+      // Add the table
+      //
+      TableHandle = 0;
+      Status = AcpiTable->InstallAcpiTable (
+                            AcpiTable,
+                              CurrentTable,
+                            ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length,
+                              &TableHandle
+                              );
+      if (EFI_ERROR(Status)) {
+        return EFI_ABORTED;
+      }
+      //
+      // If this table is the DSDT table, then update the _PRT and _PRW based on
+      // the settings from pcds
+      //
+      if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+        //
+        // Create the root handle for DSDT table
+        //
+        Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle);
+        ASSERT_EFI_ERROR (Status);
+
+        PciRootHandle = NULL;
+        PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle);
+        ASSERT (PciRootHandle != NULL);
+
+        PciDeviceInfo = NULL;
+        for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) {
+          PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]);
+
+          //
+          // Check whether this is a valid item
+          //
+          if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) {
+
+            //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress));
+
+            UpdatePRT = FALSE;
+            UpdatePRW = FALSE;
+
+            SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW);
+            //
+            // Check whether there is any valid pci routing item
+            //
+            if (UpdatePRT) {
+              //
+              // Update the pci routing information
+              //
+              //DEBUG ((EFI_D_ERROR, "Update _PRT\n"));
+              SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo);
+            }
+            //
+            // Check whether there is any valid pci routing item
+            //
+            if (UpdatePRW) {
+              //
+              // Update the pci wakeup information
+              //
+              //DEBUG ((EFI_D_ERROR, "Update _PRW\n"));
+              SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo);
+            }
+          }
+        }
+        Status = mAcpiSdt->Close (PciRootHandle);
+        ASSERT_EFI_ERROR (Status);
+        //
+        // Mark the root handle as modified , let SDT protocol recaculate the checksum
+        //
+        ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE;
+        Status = mAcpiSdt->Close (mDsdtHandle);
+        ASSERT_EFI_ERROR (Status);
+      }
+      //
+      // Increment the instance
+      //
+      Instance++;
+      CurrentTable = NULL;
+    }
+  }
+
+  gBS->FreePool (mConfigData);
+  return EFI_SUCCESS;
+}

+ 120 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.h

@@ -0,0 +1,120 @@
+/** @file
+This is an implementation of the ACPI platform driver.  Requirements for
+this driver are defined in the Tiano ACPI External Product Specification,
+revision 0.3.6.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+//
+// Statements that include other header files
+//
+
+#include <PiDxe.h>
+#include <IntelQNCDxe.h>
+#include <Platform.h>
+#include <PlatformBoards.h>
+#include <Ioh.h>
+#include <QNCCommonDefinitions.h>
+
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/MpService.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/PlatformHelperLib.h>
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include "Madt.h"
+#include "AcpiPciUpdate.h"
+
+#pragma pack(1)
+typedef struct {
+  UINT8   StartByte;
+  UINT32  NameStr;
+  UINT8   OpCode;
+  UINT16  Size;                // Hardcode to 16bit width because the table we use is fixed size
+  UINT8   NumEntries;
+} EFI_ACPI_NAME_COMMAND;
+
+typedef struct {
+  UINT8   PackageOp;
+  UINT8   PkgLeadByte;
+  UINT8   NumEntries;
+  UINT8   DwordPrefix0;
+  UINT32  CoreFreq;
+  UINT8   DwordPrefix1;
+  UINT32  Power;
+  UINT8   DwordPrefix2;
+  UINT32  TransLatency;
+  UINT8   DwordPrefix3;
+  UINT32  BMLatency;
+  UINT8   DwordPrefix4;
+  UINT32  Control;
+  UINT8   DwordPrefix5;
+  UINT32  Status;
+} EFI_PSS_PACKAGE;
+#pragma pack()
+
+
+#define AML_NAME_OP               0x08
+#define AML_METHOD_OP             0x14
+#define AML_OPREGION_OP           0x80
+#define AML_PACKAGE_OP            0x12    // Package operator.
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID           "INTEL "
+#define EFI_ACPI_OEM_TABLE_ID     0x2020204F4E414954ULL  // "TIANO   "
+#define EFI_ACPI_OEM_REVISION     0x00000002
+#define EFI_ACPI_CREATOR_ID       0x5446534D          // "MSFT"
+#define EFI_ACPI_CREATOR_REVISION 0x01000013
+
+#define ACPI_COMPATIBLE_1_0       0
+#define ACPI_COMPATIBLE_2_0       1
+#define ACPI_COMPATIBLE_3_0       2
+
+
+
+
+//
+// Private Driver Data
+//
+
+//
+// Define Union of IO APIC & Local APIC structure;
+//
+
+typedef union {
+  EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE     AcpiLocalApic;
+  EFI_ACPI_2_0_IO_APIC_STRUCTURE                  AcpiIoApic;
+  struct {
+    UINT8                                         Type;
+    UINT8                                         Length;
+  } AcpiApicCommon;
+} ACPI_APIC_STRUCTURE_PTR;
+
+#endif

+ 196 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.inf

@@ -0,0 +1,196 @@
+## @file
+# Component description file for AcpiPlatform module.
+#
+# This is an implementation of the ACPI platform driver,
+# whose requirements are from ACPI External Product Specification.
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiPlatform
+  FILE_GUID                      = 368B3649-F204-4cd0-89A8-091077C070FA
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  AcpiPlatform.c
+  AcpiPlatform.h
+  MadtPlatform.c
+  Madt.h
+  AcpiPciUpdate.c
+  AcpiPciUpdate.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  UefiLib
+  DxeServicesLib
+  PcdLib
+  IoLib
+  BaseMemoryLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  DevicePathLib
+  PlatformHelperLib
+
+[Protocols]
+  gEfiGlobalNvsAreaProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED
+  gEfiMpServiceProtocolGuid                     # PROTOCOL SOMETIMES_CONSUMED
+  gEfiAcpiSdtProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdPlatformType
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable0GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable1GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable2GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable3GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable4GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable5GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable6GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable7GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable8GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable9GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable10GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable11GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable12GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable13GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable14GlobalIrq
+
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Enable
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15SourceIrq
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15Polarity
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15TrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdInterruptOverrideSettingTable15GlobalIrq
+
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicAddress
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingGlobalInterruptBase
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingIoApicId
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiEnable
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingNmiSource
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingPolarity
+  gQuarkPlatformTokenSpaceGuid.PcdIoApicSettingTrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingNmiEnabelApicIdMask
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingAddressOverrideEnable
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingPolarity
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingTrigerMode
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicSettingLocalApicLint
+  gQuarkPlatformTokenSpaceGuid.PcdLocalApicAddressOverride
+
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress
+  gQuarkPlatformTokenSpaceGuid.PcdHpetEnable
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+
+[Depex]
+  gEfiMpServiceProtocolGuid AND gEfiAcpiTableProtocolGuid

+ 207 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/Madt.h

@@ -0,0 +1,207 @@
+/** @file
+This file describes the contents of the ACPI Multiple APIC Description
+Table (MADT).  Some additional ACPI values are defined in Acpi10.h and
+Acpi20.h.
+To make changes to the MADT, it is necessary to update the count for the
+APIC structure being updated, and to modify table found in Madt.c.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef _MADT_H
+#define _MADT_H
+
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/PcdLib.h>
+
+//
+// MADT Definitions
+//
+
+#define EFI_ACPI_OEM_MADT_REVISION 0x00000001
+
+//
+// Local APIC address
+//
+
+#define EFI_ACPI_LOCAL_APIC_ADDRESS 0xFEE00000
+
+//
+// Multiple APIC Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_1_0_PCAT_COMPAT)
+#define EFI_ACPI_2_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_2_0_PCAT_COMPAT)
+
+//
+// Define the number of each table type.
+// This is where the table layout is modified.
+//
+
+#define EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT           2
+#define EFI_ACPI_IO_APIC_COUNT                        1
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT      2
+#define EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT  0
+#define EFI_ACPI_LOCAL_APIC_NMI_COUNT                 2
+#define EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT    0
+#define EFI_ACPI_IO_SAPIC_COUNT                       0
+#define EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT          0
+#define EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT     0
+
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX  16
+
+//
+// MADT structure
+//
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI 1.0 Table structure
+//
+typedef struct {
+  EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+  EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE           LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+  EFI_ACPI_1_0_IO_APIC_STRUCTURE                        IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+  EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE      Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT > 0
+  EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE  NmiSource[EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_NMI_COUNT > 0
+  EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE                 LocalApicNmi[EFI_ACPI_LOCAL_APIC_NMI_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT > 0
+  EFI_ACPI_1_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE    LocalApicOverride[EFI_ACPI_LOCAL_APIC_OVERRIDE_COUNT];
+#endif
+
+} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+//
+// ACPI 2.0 Table structure
+//
+typedef struct {
+  EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+  EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE           LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+  EFI_ACPI_2_0_IO_APIC_STRUCTURE                        IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+  EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE      Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT > 0
+  EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE  NmiSource[EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_NMI_COUNT > 0
+  EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE                 LocalApicNmi[EFI_ACPI_LOCAL_APIC_NMI_COUNT];
+#endif
+
+#if EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT > 0
+  EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE    LocalApicOverride[EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_IO_SAPIC_COUNT > 0
+  EFI_ACPI_2_0_IO_SAPIC_STRUCTURE                       IoSapic[EFI_ACPI_IO_SAPIC_COUNT];
+#endif
+
+#if EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT > 0
+  EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE          LocalSapic[EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT];
+#endif
+
+#if EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT > 0
+  EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE     PlatformInterruptSources[EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT];
+#endif
+
+} EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+#define _PcdIntSettingTblEnable(x)       PcdGet8 (PcdInterruptOverrideSettingTable##x##Enable)
+#define PcdIntSettingTblEnable(x)        _PcdIntSettingTblEnable(x)
+
+#define _PcdIntSettingTblSourceIrq(x)    PcdGet8 (PcdInterruptOverrideSettingTable##x##Enable)
+#define PcdIntSettingTblSourceIrq(x)     _PcdIntSettingTblSourceIrq(x)
+
+#define _PcdIntSettingTblPolarity(x)     PcdGet8 (PcdInterruptOverrideSettingTable##x##Polarity)
+#define PcdIntSettingTblPolarity(x)      _PcdIntSettingTblPolarity(x)
+
+#define _PcdIntSettingTableTrigerMode(x) PcdGet8 (PcdInterruptOverrideSettingTable##x##TrigerMode)
+#define PcdIntSettingTableTrigerMode(x)  _PcdIntSettingTableTrigerMode(x)
+
+#define _PcdIntSettingTableGlobalIrq(x)  PcdGet32 (PcdInterruptOverrideSettingTable##x##GlobalIrq)
+#define PcdIntSettingTableGlobalIrq(x)   _PcdIntSettingTableGlobalIrq(x)
+
+typedef struct {
+  UINT8     Enable;
+  UINT8     SourceIrq;
+  UINT8     Polarity;
+  UINT8     TrigerMode;
+  UINT32    GlobalIrq;
+} INTERRUPT_OVERRIDE_SETTING;
+
+
+typedef struct {
+  UINT32    IoApicAddress;
+  UINT32    GlobalInterruptBase;
+  UINT8     IoApicId;
+  UINT8     NmiEnable;
+  UINT8     NmiSource;
+  UINT8     Polarity;
+  UINT8     TrigerMode;
+} IO_APIC_SETTING;
+
+typedef struct {
+  UINT8     NmiEnabelApicIdMask;
+  UINT8     AddressOverrideEnable;
+  UINT8     Polarity;
+  UINT8     TrigerMode;
+  UINT8     LocalApicLint;
+  UINT8     Reserve[3];
+  UINT32    LocalApicAddress;
+  UINT64    LocalApicAddressOverride;
+} LOCAL_APIC_SETTING;
+
+typedef struct _MADT_CONFIG_DATA {
+  INTERRUPT_OVERRIDE_SETTING MadtInterruptSetting[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX];
+  IO_APIC_SETTING        MadtIoApicSetting;
+  LOCAL_APIC_SETTING       MadtLocalApicSetting;
+}MADT_CONFIG_DATA;
+
+#pragma pack ()
+
+EFI_STATUS
+EFIAPI
+MadtTableInitialize (
+  OUT   EFI_ACPI_COMMON_HEADER  **MadtTable,
+  OUT   UINTN                   *Size
+  );
+
+
+#endif

+ 300 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c

@@ -0,0 +1,300 @@
+/** @file
+This file contains Madt Talbe initialized work.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+//
+// Statements that include other files
+//
+
+#include "AcpiPlatform.h"
+
+VOID
+InitMadtConfigData (MADT_CONFIG_DATA *mConfigData)
+{
+  mConfigData->MadtInterruptSetting[0].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable0Enable);
+  mConfigData->MadtInterruptSetting[0].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable0SourceIrq);
+  mConfigData->MadtInterruptSetting[0].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable0Polarity);
+  mConfigData->MadtInterruptSetting[0].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable0TrigerMode);
+  mConfigData->MadtInterruptSetting[0].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable0GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[1].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable1Enable);
+  mConfigData->MadtInterruptSetting[1].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable1SourceIrq);
+  mConfigData->MadtInterruptSetting[1].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable1Polarity);
+  mConfigData->MadtInterruptSetting[1].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable1TrigerMode);
+  mConfigData->MadtInterruptSetting[1].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable1GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[2].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable2Enable);
+  mConfigData->MadtInterruptSetting[2].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable2SourceIrq);
+  mConfigData->MadtInterruptSetting[2].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable2Polarity);
+  mConfigData->MadtInterruptSetting[2].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable2TrigerMode);
+  mConfigData->MadtInterruptSetting[2].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable2GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[3].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable3Enable);
+  mConfigData->MadtInterruptSetting[3].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable3SourceIrq);
+  mConfigData->MadtInterruptSetting[3].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable3Polarity);
+  mConfigData->MadtInterruptSetting[3].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable3TrigerMode);
+  mConfigData->MadtInterruptSetting[3].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable3GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[4].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable4Enable);
+  mConfigData->MadtInterruptSetting[4].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable4SourceIrq);
+  mConfigData->MadtInterruptSetting[4].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable4Polarity);
+  mConfigData->MadtInterruptSetting[4].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable4TrigerMode);
+  mConfigData->MadtInterruptSetting[4].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable4GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[5].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable5Enable);
+  mConfigData->MadtInterruptSetting[5].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable5SourceIrq);
+  mConfigData->MadtInterruptSetting[5].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable5Polarity);
+  mConfigData->MadtInterruptSetting[5].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable5TrigerMode);
+  mConfigData->MadtInterruptSetting[5].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable5GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[6].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable6Enable);
+  mConfigData->MadtInterruptSetting[6].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable6SourceIrq);
+  mConfigData->MadtInterruptSetting[6].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable6Polarity);
+  mConfigData->MadtInterruptSetting[6].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable6TrigerMode);
+  mConfigData->MadtInterruptSetting[6].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable6GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[7].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable7Enable);
+  mConfigData->MadtInterruptSetting[7].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable7SourceIrq);
+  mConfigData->MadtInterruptSetting[7].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable7Polarity);
+  mConfigData->MadtInterruptSetting[7].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable7TrigerMode);
+  mConfigData->MadtInterruptSetting[7].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable7GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[8].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable8Enable);
+  mConfigData->MadtInterruptSetting[8].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable8SourceIrq);
+  mConfigData->MadtInterruptSetting[8].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable8Polarity);
+  mConfigData->MadtInterruptSetting[8].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable8TrigerMode);
+  mConfigData->MadtInterruptSetting[8].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable8GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[9].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable9Enable);
+  mConfigData->MadtInterruptSetting[9].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable9SourceIrq);
+  mConfigData->MadtInterruptSetting[9].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable9Polarity);
+  mConfigData->MadtInterruptSetting[9].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable9TrigerMode);
+  mConfigData->MadtInterruptSetting[9].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable9GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[10].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable10Enable);
+  mConfigData->MadtInterruptSetting[10].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable10SourceIrq);
+  mConfigData->MadtInterruptSetting[10].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable10Polarity);
+  mConfigData->MadtInterruptSetting[10].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable10TrigerMode);
+  mConfigData->MadtInterruptSetting[10].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable10GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[11].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable11Enable);
+  mConfigData->MadtInterruptSetting[11].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable11SourceIrq);
+  mConfigData->MadtInterruptSetting[11].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable11Polarity);
+  mConfigData->MadtInterruptSetting[11].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable11TrigerMode);
+  mConfigData->MadtInterruptSetting[11].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable11GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[12].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable12Enable);
+  mConfigData->MadtInterruptSetting[12].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable12SourceIrq);
+  mConfigData->MadtInterruptSetting[12].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable12Polarity);
+  mConfigData->MadtInterruptSetting[12].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable12TrigerMode);
+  mConfigData->MadtInterruptSetting[12].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable12GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[13].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable13Enable);
+  mConfigData->MadtInterruptSetting[13].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable13SourceIrq);
+  mConfigData->MadtInterruptSetting[13].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable13Polarity);
+  mConfigData->MadtInterruptSetting[13].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable13TrigerMode);
+  mConfigData->MadtInterruptSetting[13].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable13GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[14].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable14Enable);
+  mConfigData->MadtInterruptSetting[14].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable14SourceIrq);
+  mConfigData->MadtInterruptSetting[14].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable14Polarity);
+  mConfigData->MadtInterruptSetting[14].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable14TrigerMode);
+  mConfigData->MadtInterruptSetting[14].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable14GlobalIrq);
+
+  mConfigData->MadtInterruptSetting[15].Enable     = PcdGet8 (PcdInterruptOverrideSettingTable15Enable);
+  mConfigData->MadtInterruptSetting[15].SourceIrq  = PcdGet8 (PcdInterruptOverrideSettingTable15SourceIrq);
+  mConfigData->MadtInterruptSetting[15].Polarity   = PcdGet8 (PcdInterruptOverrideSettingTable15Polarity);
+  mConfigData->MadtInterruptSetting[15].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable15TrigerMode);
+  mConfigData->MadtInterruptSetting[15].GlobalIrq  = PcdGet32 (PcdInterruptOverrideSettingTable15GlobalIrq);
+
+  mConfigData->MadtIoApicSetting.IoApicAddress       = (UINT32)PcdGet64(PcdIoApicBaseAddress);
+  mConfigData->MadtIoApicSetting.GlobalInterruptBase = PcdGet32 (PcdIoApicSettingGlobalInterruptBase);
+  mConfigData->MadtIoApicSetting.IoApicId            = PcdGet8 (PcdIoApicSettingIoApicId);
+  mConfigData->MadtIoApicSetting.NmiEnable           = PcdGet8 (PcdIoApicSettingNmiEnable);
+  mConfigData->MadtIoApicSetting.NmiSource           = PcdGet8 (PcdIoApicSettingNmiSource);
+  mConfigData->MadtIoApicSetting.Polarity            = PcdGet8 (PcdIoApicSettingPolarity);
+  mConfigData->MadtIoApicSetting.TrigerMode          = PcdGet8 (PcdIoApicSettingTrigerMode);
+
+  mConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask   = PcdGet8 (PcdLocalApicSettingNmiEnabelApicIdMask);
+  mConfigData->MadtLocalApicSetting.AddressOverrideEnable = PcdGet8 (PcdLocalApicSettingAddressOverrideEnable);
+  mConfigData->MadtLocalApicSetting.Polarity              = PcdGet8 (PcdLocalApicSettingPolarity);
+  mConfigData->MadtLocalApicSetting.TrigerMode            = PcdGet8 (PcdLocalApicSettingTrigerMode);
+  mConfigData->MadtLocalApicSetting.LocalApicLint         = PcdGet8 (PcdLocalApicSettingLocalApicLint);
+  mConfigData->MadtLocalApicSetting.LocalApicAddressOverride      = PcdGet64 (PcdLocalApicAddressOverride);
+  mConfigData->MadtLocalApicSetting.LocalApicAddress              = PcdGet32 (PcdCpuLocalApicBaseAddress);
+}
+UINT32
+GetAcutalMadtTableSize (
+  IN MADT_CONFIG_DATA * MadtConfigData,
+  IN INTN               NumberOfCPUs
+  )
+{
+  UINT32 MadtSize;
+  UINT8  Index;
+  MadtSize = (UINT32)(sizeof (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) +
+             sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE) * NumberOfCPUs +
+             sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE) +
+             sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE) * (MadtConfigData->MadtLocalApicSetting.AddressOverrideEnable != 0?1:0)
+             );
+  for (Index = 0; Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index ++ ) {
+    if (MadtConfigData->MadtInterruptSetting[Index].Enable != 0) {
+      MadtSize += sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+    }
+  }
+  for (Index = 0; Index < NumberOfCPUs; Index ++ ) {
+    if (0 != (MadtConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))) {
+      MadtSize += sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE);
+    }
+  }
+  if (0 != MadtConfigData->MadtIoApicSetting.NmiEnable) {
+    MadtSize += sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE);
+  }
+  return MadtSize;
+}
+
+//
+// Init Multiple APIC Description Table
+//
+EFI_STATUS
+MadtTableInitialize (
+  OUT   EFI_ACPI_COMMON_HEADER  **MadtTable,
+  OUT   UINTN                   *Size
+  )
+{
+  EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
+  EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE         *ProcLocalApic;
+  EFI_ACPI_2_0_IO_APIC_STRUCTURE                      *IoApic;
+  EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE    *InterruptSourceOverride;
+  EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE  *IoApicNmiSource;
+  EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE                 *LocalApicNmiSource;
+  EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE    *LocalApicAddressOverride;
+
+  EFI_MP_SERVICES_PROTOCOL                            *MpService;
+  UINTN                                               NumberOfCPUs;
+  UINTN                                               NumberOfEnabledCPUs;
+  MADT_CONFIG_DATA                                    MadtConfigData;
+
+  UINT32      MadtSize;
+  UINTN       Index;
+  EFI_STATUS  Status;
+
+
+  ASSERT (NULL != MadtTable);
+  ASSERT (NULL != Size);
+  //
+  // Init Madt table data
+  //
+  InitMadtConfigData (&MadtConfigData);
+  //
+  // Find the MP Protocol. This is an MP platform, so MP protocol must be
+  // there.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiMpServiceProtocolGuid,
+                  NULL,
+                  (VOID **)&MpService
+                  );
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Determine the number of processors
+  //
+  MpService->GetNumberOfProcessors (
+              MpService,
+              &NumberOfCPUs,
+              &NumberOfEnabledCPUs
+              );
+  //ASSERT (NumberOfCPUs <= 2 && NumberOfCPUs > 0);
+  MadtSize = GetAcutalMadtTableSize (&MadtConfigData, NumberOfCPUs);
+  Madt = (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)AllocateZeroPool (MadtSize);
+  ASSERT (Madt != NULL);
+  //
+  // Initialize MADT Header information
+  //
+  Madt->Header.Signature    = EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE;
+  Madt->Header.Length       = MadtSize;
+  Madt->Header.Revision     = EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION;
+  Madt->Header.OemTableId   = EFI_ACPI_OEM_TABLE_ID;
+  Madt->Header.OemRevision  = EFI_ACPI_OEM_MADT_REVISION;
+  Madt->Header.CreatorId    = EFI_ACPI_CREATOR_ID;
+  Madt->LocalApicAddress    = MadtConfigData.MadtLocalApicSetting.LocalApicAddress;
+  Madt->Flags               = EFI_ACPI_2_0_MULTIPLE_APIC_FLAGS;
+  CopyMem (Madt->Header.OemId, EFI_ACPI_OEM_ID, 6);
+
+  ProcLocalApic = (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *) (Madt + 1);
+  //
+  // Initialization of Processor's local APICs
+  //
+  for (Index = 0;Index < NumberOfCPUs; Index++) {
+    ProcLocalApic[Index].Type             = EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC;
+    ProcLocalApic[Index].Length           = sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
+    ProcLocalApic[Index].AcpiProcessorId  = (UINT8)(Index + 1);
+    ProcLocalApic[Index].ApicId           = 0xff;
+    ProcLocalApic[Index].Flags            = 0;
+  }
+  //
+  // Initialization of IO APIC.
+  // Note: Here assumes that there must be one and only one IO APIC in platform.
+  //
+  IoApic = (EFI_ACPI_2_0_IO_APIC_STRUCTURE *) (&ProcLocalApic[Index]);
+  IoApic->Type                      = EFI_ACPI_2_0_IO_APIC;
+  IoApic->Length                    = sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE);
+  IoApic->IoApicId                  = MadtConfigData.MadtIoApicSetting.IoApicId;
+  IoApic->IoApicAddress             = MadtConfigData.MadtIoApicSetting.IoApicAddress;
+  IoApic->GlobalSystemInterruptBase = MadtConfigData.MadtIoApicSetting.GlobalInterruptBase;
+
+  InterruptSourceOverride = (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *) (IoApic + 1);
+  for (Index = 0;Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index++ ){
+    if (MadtConfigData.MadtInterruptSetting[Index].Enable) {
+      InterruptSourceOverride->Type   = EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE;
+      InterruptSourceOverride->Length = sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+      InterruptSourceOverride->Bus    = 0;
+      InterruptSourceOverride->Source = MadtConfigData.MadtInterruptSetting[Index].SourceIrq;
+      InterruptSourceOverride->Flags  = ((MadtConfigData.MadtInterruptSetting[Index].TrigerMode & 0x03) << 2) | (MadtConfigData.MadtInterruptSetting[Index].Polarity & 0x03);
+      InterruptSourceOverride->GlobalSystemInterrupt  = MadtConfigData.MadtInterruptSetting[Index].GlobalIrq;
+      InterruptSourceOverride++;
+    }
+  }
+  //
+  // support NMI source configuration.
+  //
+  IoApicNmiSource = (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *) InterruptSourceOverride;
+  if ((BOOLEAN) MadtConfigData.MadtIoApicSetting.NmiEnable) {
+    IoApicNmiSource->Type   = EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE;
+    IoApicNmiSource->Length = sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE);
+    IoApicNmiSource->Flags  = ((MadtConfigData.MadtIoApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtIoApicSetting.Polarity & 0x03);
+    IoApicNmiSource->GlobalSystemInterrupt = MadtConfigData.MadtIoApicSetting.NmiSource;
+    IoApicNmiSource ++;
+  }
+  //
+  // Assume each processor has same NMI interrupt source.
+  //
+  LocalApicNmiSource = (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE *) IoApicNmiSource;
+  for (Index = 0;Index < NumberOfCPUs; Index++) {
+    if (0 != (MadtConfigData.MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))){
+      LocalApicNmiSource->Type          = EFI_ACPI_2_0_LOCAL_APIC_NMI;
+      LocalApicNmiSource->Length        = sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE);
+      LocalApicNmiSource->LocalApicLint = MadtConfigData.MadtLocalApicSetting.LocalApicLint;
+      LocalApicNmiSource->Flags         = ((MadtConfigData.MadtLocalApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtLocalApicSetting.Polarity & 0x03);
+      LocalApicNmiSource->AcpiProcessorId = (UINT8)(Index + 1);
+      LocalApicNmiSource++;
+    }
+  }
+
+  LocalApicAddressOverride = (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *) LocalApicNmiSource;
+  if ((BOOLEAN) MadtConfigData.MadtLocalApicSetting.AddressOverrideEnable) {
+    LocalApicAddressOverride->Type    = EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE;
+    LocalApicAddressOverride->Length  = sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE);
+    LocalApicAddressOverride->LocalApicAddress = MadtConfigData.MadtLocalApicSetting.LocalApicAddressOverride;
+    LocalApicAddressOverride++;
+  }
+  *Size       = MadtSize;
+  *MadtTable  = (EFI_ACPI_COMMON_HEADER *) Madt;
+
+  return EFI_SUCCESS;
+}

+ 77 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/BootScriptExecutorDxe.inf

@@ -0,0 +1,77 @@
+## @file
+# Boot Script Executor Module
+#
+# This is a standalone Boot Script Executor. Standalone means it does not
+# depends on any PEI or DXE service.
+#
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BootScriptExecutorDxe
+  FILE_GUID                      = FA20568B-548B-4b2b-81EF-1BA08D4A3CEC
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = BootScriptExecutorEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  ScriptExecute.h
+  ScriptExecute.c
+
+[Sources.Ia32]
+  IA32/SetIdtEntry.c
+  IA32/S3Asm.asm
+  IA32/S3Asm.S
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+  TimerLib
+  PcdLib
+  BaseMemoryLib
+  SmbusLib
+  UefiDriverEntryPoint
+  BaseLib
+  PciLib
+  IoLib
+  S3BootScriptLib
+  PeCoffLib
+  DxeServicesLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  CacheMaintenanceLib
+  UefiLib
+  DebugAgentLib
+  LockBoxLib
+  IntelQNCLib
+  QNCAccessLib
+
+[Guids]
+  gEfiBootScriptExecutorVariableGuid
+  gEfiBootScriptExecutorContextGuid
+  gPerformanceProtocolGuid
+  gEfiEventExitBootServicesGuid
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+
+[Depex]
+  gEfiLockBoxProtocolGuid

+ 44 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.S

@@ -0,0 +1,44 @@
+## @file
+#
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+#-----------------------------------------
+#VOID
+#AsmTransferControl (
+#  IN   UINT32           S3WakingVector,
+#  IN   UINT32           AcpiLowMemoryBase
+#  );
+#-----------------------------------------
+
+ASM_GLOBAL ASM_PFX(AsmTransferControl)
+ASM_PFX(AsmTransferControl):
+    # S3WakingVector    :DWORD
+    # AcpiLowMemoryBase :DWORD
+    pushl %ebp
+    movl  %esp,%ebp
+    leal  LABLE, %eax
+    pushl $0x28             # CS
+    pushl %eax
+    movl  8(%ebp),%ecx
+    shrdl $20,%ecx,%ebx
+    andl  $0xf,%ecx
+    movw  %cx,%bx
+    movl  %ebx, jmp_addr
+    lret
+LABLE:
+    .byte 0xb8,0x30,0       # mov ax, 30h as selector
+    movw  %ax,%ds
+    movw  %ax,%es
+    movw  %ax,%fs
+    movw  %ax,%gs
+    movw  %ax,%ss
+    movl  %cr0, %eax        # Get control register 0
+    .byte 0x66
+    .byte 0x83,0xe0,0xfe    # and    eax, 0fffffffeh  ; Clear PE bit (bit #0)
+    .byte 0xf,0x22,0xc0     # mov    cr0, eax         ; Activate real mode
+    .byte 0xea              # jmp far @jmp_addr
+jmp_addr:
+    .long    0
+

+ 51 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/S3Asm.asm

@@ -0,0 +1,51 @@
+;; @file
+;   This is the assembly code for transferring to control to OS S3 waking vector
+;   for IA32 platform
+;
+; Copyright (c) 2013-2015 Intel Corporation.
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+
+    .586P
+    .model  flat,C
+    .code
+
+;-----------------------------------------
+;VOID
+;AsmTransferControl (
+;  IN   UINT32           S3WakingVector,
+;  IN   UINT32           AcpiLowMemoryBase
+;  );
+;-----------------------------------------
+
+AsmTransferControl  PROC
+    ; S3WakingVector    :DWORD
+    ; AcpiLowMemoryBase :DWORD
+    push  ebp
+    mov   ebp, esp
+    lea   eax, @F
+    push  28h               ; CS
+    push  eax
+    mov   ecx, [ebp + 8]
+    shrd  ebx, ecx, 20
+    and   ecx, 0fh
+    mov   bx, cx
+    mov   @jmp_addr, ebx
+    retf
+@@:
+    DB    0b8h, 30h, 0      ; mov ax, 30h as selector
+    mov   ds, ax
+    mov   es, ax
+    mov   fs, ax
+    mov   gs, ax
+    mov   ss, ax
+    mov   eax, cr0          ; Get control register 0
+    DB    66h
+    DB    83h, 0e0h, 0feh   ; and    eax, 0fffffffeh  ; Clear PE bit (bit #0)
+    DB    0fh, 22h, 0c0h    ; mov    cr0, eax         ; Activate real mode
+    DB    0eah              ; jmp far @jmp_addr
+@jmp_addr DD  ?
+
+AsmTransferControl  ENDP
+
+    END

+ 57 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/IA32/SetIdtEntry.c

@@ -0,0 +1,57 @@
+/** @file
+Set a IDT entry for debug purpose
+
+Set a IDT entry for interrupt vector 3 for debug purpose for IA32 platform
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "ScriptExecute.h"
+//
+// INTERRUPT_GATE_DESCRIPTOR and SetIdtEntry () are used to setup IDT to do debug
+//
+
+#pragma pack(1)
+
+typedef struct {
+  UINT16  OffsetLow;
+  UINT16  SegmentSelector;
+  UINT16  Attributes;
+  UINT16  OffsetHigh;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#define INTERRUPT_GATE_ATTRIBUTE   0x8e00
+
+#pragma pack()
+/**
+  Set a IDT entry for interrupt vector 3 for debug purpose.
+
+  @param  AcpiS3Context  a pointer to a structure of ACPI_S3_CONTEXT
+
+**/
+VOID
+SetIdtEntry (
+  IN ACPI_S3_CONTEXT     *AcpiS3Context
+  )
+{
+  INTERRUPT_GATE_DESCRIPTOR                     *IdtEntry;
+  IA32_DESCRIPTOR                               *IdtDescriptor;
+  UINTN                                         S3DebugBuffer;
+
+  //
+  // Restore IDT for debug
+  //
+  IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);
+  IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));
+  S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);
+
+  IdtEntry->OffsetLow       = (UINT16)S3DebugBuffer;
+  IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();
+  IdtEntry->Attributes      = (UINT16)INTERRUPT_GATE_ATTRIBUTE;
+  IdtEntry->OffsetHigh      = (UINT16)(S3DebugBuffer >> 16);
+
+  AsmWriteIdtr (IdtDescriptor);
+}
+

+ 379 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.c

@@ -0,0 +1,379 @@
+/** @file
+This is the code for Boot Script Executer module.
+
+This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
+in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ScriptExecute.h"
+
+#pragma pack(1)
+typedef union {
+  struct {
+    UINT32  LimitLow    : 16;
+    UINT32  BaseLow     : 16;
+    UINT32  BaseMid     : 8;
+    UINT32  Type        : 4;
+    UINT32  System      : 1;
+    UINT32  Dpl         : 2;
+    UINT32  Present     : 1;
+    UINT32  LimitHigh   : 4;
+    UINT32  Software    : 1;
+    UINT32  Reserved    : 1;
+    UINT32  DefaultSize : 1;
+    UINT32  Granularity : 1;
+    UINT32  BaseHigh    : 8;
+  } Bits;
+  UINT64  Uint64;
+} IA32_GDT;
+
+#pragma pack()
+
+EFI_GUID              mBootScriptExecutorImageGuid = {
+  0x9a8d3433, 0x9fe8, 0x42b6, {0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b}
+};
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
+/* selector { Global Segment Descriptor                              } */
+/* 0x00 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
+/* 0x08 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
+/* 0x10 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
+/* 0x18 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
+/* 0x20 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
+/* 0x28 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
+/* 0x30 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
+/* 0x38 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  1, 0,  1,  0}},
+/* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
+  sizeof (mGdtEntries) - 1,
+  (UINTN) mGdtEntries
+  };
+
+/**
+  Entry function of Boot script exector. This function will be executed in
+  S3 boot path.
+  This function should not return, because it is invoked by switch stack.
+
+  @param  AcpiS3Context    a pointer to a structure of ACPI_S3_CONTEXT
+  @param  PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
+
+  @retval EFI_INVALID_PARAMETER - OS waking vector not found
+  @retval EFI_UNSUPPORTED - something wrong when we resume to OS
+**/
+EFI_STATUS
+EFIAPI
+S3BootScriptExecutorEntryFunction (
+  IN ACPI_S3_CONTEXT       *AcpiS3Context,
+  IN PEI_S3_RESUME_STATE   *PeiS3ResumeState
+  )
+{
+  EFI_STATUS                                    Status;
+
+  //
+  // Disable interrupt of Debug timer, since new IDT table cannot handle it.
+  //
+  SaveAndSetDebugTimerInterrupt (FALSE);
+
+  //
+  // Restore IDT for debug
+  //
+  SetIdtEntry (AcpiS3Context);
+
+  //
+  // Initialize Debug Agent to support source level debug in S3 path.
+  //
+  InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL);
+
+  //
+  // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
+  // for that parameter.
+  //
+  Status = S3BootScriptExecute ();
+
+  AsmWbinvd ();
+
+  //
+  // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
+  //
+  if (PeiS3ResumeState != 0) {
+    //
+    // Need report status back to S3ResumePeim.
+    // If boot script execution is failed, S3ResumePeim wil report the error status code.
+    //
+    PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
+    //
+    // IA32 S3 Resume
+    //
+    DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
+    PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformTransferControl16;
+
+    SwitchStack (
+      (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
+      (VOID *)(UINTN)AcpiS3Context,
+      (VOID *)(UINTN)PeiS3ResumeState,
+      (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
+      );
+
+    //
+    // Never run to here
+    //
+    CpuDeadLoop();
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Never run to here
+  //
+  CpuDeadLoop();
+  return EFI_UNSUPPORTED;
+}
+/**
+  Entrypoint of Boot script exector driver, this function will be executed in
+  normal boot phase and invoked by DXE dispatch.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+**/
+EFI_STATUS
+EFIAPI
+BootScriptExecutorEntryPoint (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  UINT8                                         *Buffer;
+  UINTN                                         BufferSize;
+  UINTN                                         Pages;
+  EFI_PHYSICAL_ADDRESS                          FfsBuffer;
+  PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;
+  BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;
+  EFI_PHYSICAL_ADDRESS                          BootScriptExecutorBuffer;
+  EFI_STATUS                                    Status;
+  VOID                                          *DevicePath;
+  EFI_HANDLE                                    NewImageHandle;
+
+  //
+  // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
+  // point is loaded by DXE code which is the first time loaded. or else, it is already
+  // be reloaded be itself.This is a work-around
+  //
+  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
+  if (EFI_ERROR (Status)) {
+
+      //
+      // This is the first-time loaded by DXE core. reload itself to NVS mem
+      //
+      //
+      // A workarouond: Here we install a dummy handle
+      //
+      NewImageHandle = NULL;
+      Status = gBS->InstallProtocolInterface (
+                  &NewImageHandle,
+                  &gEfiCallerIdGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+
+      Status = GetSectionFromAnyFv  (
+                 &gEfiCallerIdGuid,
+                 EFI_SECTION_PE32,
+                 0,
+                 (VOID **) &Buffer,
+                 &BufferSize
+                 );
+      ImageContext.Handle    = Buffer;
+      ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+      //
+      // Get information about the image being loaded
+      //
+      Status = PeCoffLoaderGetImageInfo (&ImageContext);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
+      FfsBuffer = 0xFFFFFFFF;
+      Status = gBS->AllocatePages (
+                    AllocateMaxAddress,
+                    EfiACPIMemoryNVS,
+                    Pages,
+                    &FfsBuffer
+                    );
+      if (EFI_ERROR (Status)) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+      //
+      // Align buffer on section boundary
+      //
+      ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+      ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+      //
+      // Load the image to our new buffer
+      //
+      Status = PeCoffLoaderLoadImage (&ImageContext);
+      if (EFI_ERROR (Status)) {
+        gBS->FreePages (FfsBuffer, Pages);
+        return Status;
+      }
+
+      //
+      // Relocate the image in our new buffer
+      //
+      Status = PeCoffLoaderRelocateImage (&ImageContext);
+
+      if (EFI_ERROR (Status)) {
+        PeCoffLoaderUnloadImage (&ImageContext);
+        gBS->FreePages (FfsBuffer, Pages);
+        return Status;
+      }
+      //
+      // Flush the instruction cache so the image data is written before we execute it
+      //
+      InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+      Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
+      if (EFI_ERROR (Status)) {
+        gBS->FreePages (FfsBuffer, Pages);
+        return Status;
+      }
+      //
+      // Additional step for BootScript integrity
+      // Save BootScriptExecutor image
+      //
+      Status = SaveLockBox (
+                 &mBootScriptExecutorImageGuid,
+                 (VOID *)(UINTN)ImageContext.ImageAddress,
+                 (UINTN)ImageContext.ImageSize
+                 );
+      ASSERT_EFI_ERROR (Status);
+
+      Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+      ASSERT_EFI_ERROR (Status);
+
+    } else {
+      //
+      // the entry point is invoked after reloading. following code only run in  ACPI NVS
+      //
+      BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
+
+      BootScriptExecutorBuffer = 0xFFFFFFFF;
+      Pages = EFI_SIZE_TO_PAGES(BufferSize);
+      Status = gBS->AllocatePages (
+                      AllocateMaxAddress,
+                      EfiACPIMemoryNVS,
+                      Pages,
+                      &BootScriptExecutorBuffer
+                      );
+      if (EFI_ERROR (Status)) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
+      EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ;
+
+      Status = SaveLockBox (
+                 &gEfiBootScriptExecutorVariableGuid,
+                 &BootScriptExecutorBuffer,
+                 sizeof(BootScriptExecutorBuffer)
+                 );
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Additional step for BootScript integrity
+      // Save BootScriptExecutor context
+      //
+      Status = SaveLockBox (
+                 &gEfiBootScriptExecutorContextGuid,
+                 EfiBootScriptExecutorVariable,
+                 sizeof(*EfiBootScriptExecutorVariable)
+                 );
+      ASSERT_EFI_ERROR (Status);
+
+      Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+      ASSERT_EFI_ERROR (Status);
+
+    }
+
+    return EFI_SUCCESS;
+}
+
+/**
+  Platform specific mechanism to transfer control to 16bit OS waking vector
+
+  @param[in] AcpiWakingVector    The 16bit OS waking vector
+  @param[in] AcpiLowMemoryBase   A buffer under 1M which could be used during the transfer
+
+**/
+VOID
+PlatformTransferControl16 (
+  IN UINT32       AcpiWakingVector,
+  IN UINT32       AcpiLowMemoryBase
+  )
+{
+  UINT32      NewValue;
+  UINT64      BaseAddress;
+  UINT64      SmramLength;
+  UINTN       Index;
+
+  DEBUG (( EFI_D_INFO, "PlatformTransferControl - Entry\r\n"));
+
+  //
+  // Need to make sure the GDT is loaded with values that support long mode and real mode.
+  //
+  AsmWriteGdtr (&mGdt);
+
+  //
+  // Disable eSram block (this will also clear/zero eSRAM)
+  // We only use eSRAM in the PEI phase. Disable now that we are resuming the OS
+  //
+  NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK);
+  NewValue |= BLOCK_DISABLE_PG;
+  QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue);
+
+  //
+  // Update HMBOUND to top of DDR3 memory and LOCK
+  // We disabled eSRAM so now we move HMBOUND down to top of DDR3
+  //
+  QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength);
+  NewValue = (UINT32)(BaseAddress + SmramLength);
+  DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue));
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK));
+
+  //
+  // Lock all IMR regions now that HMBOUND is locked
+  //
+  for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index += 4) {
+    NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);
+    NewValue |= IMR_LOCK;
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index, NewValue);
+  }
+
+  //
+  // Call ASM routine to switch to real mode and jump to 16bit OS waking vector
+  //
+  AsmTransferControl(AcpiWakingVector, 0);
+
+  //
+  // Never run to here
+  //
+  CpuDeadLoop();
+}
+
+
+
+

+ 70 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/Dxe/BootScriptExecutorDxe/ScriptExecute.h

@@ -0,0 +1,70 @@
+/** @file
+The header file for Boot Script Executer module.
+
+This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
+in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef _SCRIPT_EXECUTE_H_
+#define _SCRIPT_EXECUTE_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/QNCAccessLib.h>
+
+#include <Guid/AcpiS3Context.h>
+#include <Guid/BootScriptExecutorVariable.h>
+#include <Guid/EventGroup.h>
+#include <IndustryStandard/Acpi.h>
+
+/**
+  a ASM function to transfer control to OS.
+
+  @param  S3WakingVector  The S3 waking up vector saved in ACPI Facs table
+  @param  AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+VOID
+AsmTransferControl (
+  IN   UINT32           S3WakingVector,
+  IN   UINT32           AcpiLowMemoryBase
+  );
+
+VOID
+SetIdtEntry (
+  IN ACPI_S3_CONTEXT     *AcpiS3Context
+  );
+
+/**
+  Platform specific mechanism to transfer control to 16bit OS waking vector
+
+  @param[in] AcpiWakingVector    The 16bit OS waking vector
+  @param[in] AcpiLowMemoryBase   A buffer under 1M which could be used during the transfer
+
+**/
+VOID
+PlatformTransferControl16 (
+  IN UINT32       AcpiWakingVector,
+  IN UINT32       AcpiLowMemoryBase
+  );
+
+#endif //_SCRIPT_EXECUTE_H_

+ 1011 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c

@@ -0,0 +1,1011 @@
+/** @file
+ACPISMM Driver implementation file.
+
+This is QNC Smm platform driver
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include <AcpiSmmPlatform.h>
+
+#define PCILIB_TO_COMMON_ADDRESS(Address) \
+        ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))
+
+//
+// Modular variables needed by this driver
+//
+EFI_ACPI_SMM_DEV                 mAcpiSmm;
+
+UINT8  mPciCfgRegTable[] = {
+  //
+  // Logic to decode the table masks to arrive at the registers saved
+  // Dword Registers are saved. For a given mask, the Base+offset register
+  // will be saved as in the table below.
+  // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06
+  //     Base      0x00   0x20   0x40  0x60  0x80  0xA0  0xC0  0xE0
+  // Mask  offset
+  // 0x01   0x00
+  // 0x02   0x04
+  // 0x04   0x08
+  // 0x08   0x0C
+  // 0x10   0x10
+  // 0x20   0x14
+  // 0x40   0x18
+  // 0x80   0x1C
+  //
+
+  //
+  // Bus,   Dev,  Func,
+  // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+  // Only Bus 0 device is supported now
+  //
+
+  //
+  // Quark South Cluster devices
+  //
+  PCI_DEVICE   (0, 20, 0),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 1),
+  PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 2),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 3),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),
+
+  PCI_DEVICE   (0, 20, 4),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 5),
+  PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 6),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 20, 7),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 21, 0),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 21, 1),
+  PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 21, 2),
+  PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  //
+  // Quark North Cluster devices
+  //
+  PCI_DEVICE   (0, 0, 0),
+  PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 23, 0),
+  PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 23, 1),
+  PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+  PCI_DEVICE   (0, 31, 0),
+  PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),
+
+  PCI_DEVICE_END
+};
+
+EFI_PLATFORM_TYPE                         mPlatformType;
+
+  // These registers have to set in byte order
+const UINT8  QNCS3SaveExtReg[] = {
+    QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+    QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+    QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings
+    QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,
+    QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,
+    QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,
+
+    0xFF
+    };
+
+/**
+  Allocate EfiACPIMemoryNVS below 4G memory address.
+
+  This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+  @param Size   Size of memory to allocate.
+
+  @return       Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+  IN UINTN  Size
+  )
+{
+  UINTN                 Pages;
+  EFI_PHYSICAL_ADDRESS  Address;
+  EFI_STATUS            Status;
+  VOID*                 Buffer;
+
+  Pages = EFI_SIZE_TO_PAGES (Size);
+  Address = 0xffffffff;
+
+  Status  = gBS->AllocatePages (
+                   AllocateMaxAddress,
+                   EfiACPIMemoryNVS,
+                   Pages,
+                   &Address
+                   );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  Buffer = (VOID *) (UINTN) Address;
+  ZeroMem (Buffer, Size);
+
+  return Buffer;
+}
+
+EFI_STATUS
+EFIAPI
+ReservedS3Memory (
+  UINTN  SystemMemoryLength
+
+  )
+/*++
+
+Routine Description:
+
+  Reserved S3 memory for InstallS3Memory
+
+Arguments:
+
+
+Returns:
+
+  EFI_OUT_OF_RESOURCES  -  Insufficient resources to complete function.
+  EFI_SUCCESS           -  Function has completed successfully.
+
+--*/
+{
+
+  VOID                                      *GuidHob;
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK            *DescriptorBlock;
+  VOID                                      *AcpiReservedBase;
+
+  UINTN                                     TsegIndex;
+  UINTN                                     TsegSize;
+  UINTN                                     TsegBase;
+  RESERVED_ACPI_S3_RANGE                    *AcpiS3Range;
+  //
+  // Get Hob list for SMRAM desc
+  //
+  GuidHob    = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+  ASSERT (GuidHob);
+  DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+  ASSERT (DescriptorBlock);
+
+  //
+  // Use the hob to get SMRAM capabilities
+  //
+  TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;
+  ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));
+  TsegBase  = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;
+  TsegSize  = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;
+
+  DEBUG ((EFI_D_INFO, "SMM  Base: %08X\n", TsegBase));
+  DEBUG ((EFI_D_INFO, "SMM  Size: %08X\n", TsegSize));
+
+  //
+  // Now find the location of the data structure that is used to store the address
+  // of the S3 reserved memory.
+  //
+  AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);
+
+  //
+  // Allocate reserved ACPI memory for S3 resume.  Pointer to this region is
+  // stored in SMRAM in the first page of TSEG.
+  //
+  AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));
+  if (AcpiReservedBase != NULL) {
+    AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;
+    AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
+  }
+  AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;
+
+  DEBUG ((EFI_D_INFO, "S3 Memory  Base:    %08X\n", AcpiS3Range->AcpiReservedMemoryBase));
+  DEBUG ((EFI_D_INFO, "S3 Memory  Size:    %08X\n", AcpiS3Range->AcpiReservedMemorySize));
+  DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+InitAcpiSmmPlatform (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+/*++
+
+Routine Description:
+
+  Initializes the SMM S3 Handler Driver.
+
+Arguments:
+
+  ImageHandle  -  The image handle of Sleep State Wake driver.
+  SystemTable  -  The starndard EFI system table.
+
+Returns:
+
+  EFI_OUT_OF_RESOURCES  -  Insufficient resources to complete function.
+  EFI_SUCCESS           -  Function has completed successfully.
+  Other                 -  Error occured during execution.
+
+--*/
+{
+  EFI_STATUS                      Status;
+  EFI_GLOBAL_NVS_AREA_PROTOCOL    *AcpiNvsProtocol = NULL;
+  UINTN                           MemoryLength;
+  EFI_PEI_HOB_POINTERS            Hob;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiGlobalNvsAreaProtocolGuid,
+                  NULL,
+                  (VOID **) &AcpiNvsProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  mAcpiSmm.BootScriptSaved  = 0;
+
+  mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);
+
+  //
+  // Calculate the system memory length by memory hobs
+  //
+  MemoryLength  = 0x100000;
+  Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+  ASSERT (Hob.Raw != NULL);
+  while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
+    if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+      //
+      // Skip the memory region below 1MB
+      //
+      if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+        MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;
+      }
+    }
+    Hob.Raw = GET_NEXT_HOB (Hob);
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+  }
+
+  ReservedS3Memory(MemoryLength);
+
+  //
+  // Locate and Register to Parent driver
+  //
+  Status = RegisterToDispatchDriver ();
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterToDispatchDriver (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Register to dispatch driver.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  EFI_SUCCESS  -  Successfully init the device.
+  Other        -  Error occured whening calling Dxe lib functions.
+
+--*/
+{
+  UINTN                         Length;
+  EFI_STATUS                    Status;
+  EFI_SMM_SX_DISPATCH2_PROTOCOL  *SxDispatch;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
+  EFI_SMM_SX_REGISTER_CONTEXT   *EntryDispatchContext;
+  EFI_SMM_SX_REGISTER_CONTEXT   *EntryS1DispatchContext;
+  EFI_SMM_SX_REGISTER_CONTEXT   *EntryS3DispatchContext;
+  EFI_SMM_SX_REGISTER_CONTEXT   *EntryS4DispatchContext;
+  EFI_SMM_SX_REGISTER_CONTEXT   *EntryS5DispatchContext;
+  EFI_SMM_SW_REGISTER_CONTEXT   *SwContext;
+  EFI_SMM_SW_REGISTER_CONTEXT   *AcpiDisableSwContext;
+  EFI_SMM_SW_REGISTER_CONTEXT   *AcpiEnableSwContext;
+
+  Status = gSmst->SmmLocateProtocol (
+                  &gEfiSmmSxDispatch2ProtocolGuid,
+                  NULL,
+                  (VOID **) &SxDispatch
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gSmst->SmmLocateProtocol (
+                  &gEfiSmmSwDispatch2ProtocolGuid,
+                  NULL,
+                  (VOID **) &SwDispatch
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;
+  Status = gSmst->SmmAllocatePool (
+                      EfiRuntimeServicesData,
+                      Length,
+                      (VOID **) &EntryDispatchContext
+                      );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  SetMem (EntryDispatchContext, Length, 0);
+
+  EntryS1DispatchContext  = EntryDispatchContext++;
+  EntryS3DispatchContext  = EntryDispatchContext++;
+  EntryS4DispatchContext  = EntryDispatchContext++;
+  EntryS5DispatchContext  = EntryDispatchContext++;
+
+  SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;
+  AcpiDisableSwContext = SwContext++;
+  AcpiEnableSwContext  = SwContext++;
+
+  //
+  // Register the enable handler
+  //
+  AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;
+  Status = SwDispatch->Register (
+                        SwDispatch,
+                        EnableAcpiCallback,
+                        AcpiEnableSwContext,
+                        &(mAcpiSmm.DisableAcpiHandle)
+                        );
+
+  //
+  // Register the disable handler
+  //
+  AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;
+  Status = SwDispatch->Register (
+                        SwDispatch,
+                        DisableAcpiCallback,
+                        AcpiDisableSwContext,
+                        &(mAcpiSmm.EnableAcpiHandle)
+                        );
+
+
+  //
+  // Register entry phase call back function for S1
+  //
+  EntryS1DispatchContext->Type  = SxS1;
+  EntryS1DispatchContext->Phase = SxEntry;
+  Status = SxDispatch->Register (
+                        SxDispatch,
+                        SxSleepEntryCallBack,
+                        EntryS1DispatchContext,
+                        &(mAcpiSmm.S1SleepEntryHandle)
+                        );
+
+  //
+  // Register entry phase call back function
+  //
+  EntryS3DispatchContext->Type  = SxS3;
+  EntryS3DispatchContext->Phase = SxEntry;
+  Status = SxDispatch->Register (
+                        SxDispatch,
+                        SxSleepEntryCallBack,
+                        EntryS3DispatchContext,
+                        &(mAcpiSmm.S3SleepEntryHandle)
+                        );
+
+  //
+  // Register entry phase call back function for S4
+  //
+  EntryS4DispatchContext->Type  = SxS4;
+  EntryS4DispatchContext->Phase = SxEntry;
+  Status = SxDispatch->Register (
+                        SxDispatch,
+                        SxSleepEntryCallBack,
+                        EntryS4DispatchContext,
+                        &(mAcpiSmm.S4SleepEntryHandle)
+                        );
+
+  //
+  // Register callback for S5 in order to workaround the LAN shutdown issue
+  //
+  EntryS5DispatchContext->Type  = SxS5;
+  EntryS5DispatchContext->Phase = SxEntry;
+  Status = SxDispatch->Register (
+                        SxDispatch,
+                        SxSleepEntryCallBack,
+                        EntryS5DispatchContext,
+                        &(mAcpiSmm.S5SoftOffEntryHandle)
+                        );
+
+  return Status;
+}
+
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  )
+/*++
+
+Routine Description:
+  SMI handler to restore QncS3 code & context for S3 path
+  This will be only triggered when BootScript got executed during resume
+
+Arguments:
+  DispatchHandle  - EFI Handle
+  DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+  Nothing
+
+--*/
+{
+  //
+  // Restore to original address by default
+  //
+  RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);
+  RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DisableAcpiCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  )
+/*++
+
+Routine Description:
+  SMI handler to disable ACPI mode
+
+  Dispatched on reads from APM port with value 0xA1
+
+  ACPI events are disabled and ACPI event status is cleared.
+  SCI mode is then disabled.
+   Clear all ACPI event status and disable all ACPI events
+   Disable PM sources except power button
+   Clear status bits
+   Disable GPE0 sources
+   Clear status bits
+   Disable GPE1 sources
+   Clear status bits
+   Disable SCI
+
+Arguments:
+  DispatchHandle  - EFI Handle
+  DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+  Nothing
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT16      Pm1Cnt;
+
+  Status = GetAllQncPmBase (gSmst);
+  ASSERT_EFI_ERROR (Status);
+  Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+
+  //
+  // Disable SCI
+  //
+  Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;
+
+  IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EnableAcpiCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  )
+/*++
+
+Routine Description:
+  SMI handler to enable ACPI mode
+
+  Dispatched on reads from APM port with value 0xA0
+
+  Disables the SW SMI Timer.
+  ACPI events are disabled and ACPI event status is cleared.
+  SCI mode is then enabled.
+
+   Disable SW SMI Timer
+
+   Clear all ACPI event status and disable all ACPI events
+   Disable PM sources except power button
+   Clear status bits
+
+   Disable GPE0 sources
+   Clear status bits
+
+   Disable GPE1 sources
+   Clear status bits
+
+   Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+
+   Enable SCI
+
+Arguments:
+  DispatchHandle  - EFI Handle
+  DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+  Nothing
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT32      SmiEn;
+  UINT16      Pm1Cnt;
+  UINT8       Data8;
+
+  Status  = GetAllQncPmBase (gSmst);
+  ASSERT_EFI_ERROR (Status);
+
+  SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+
+  //
+  // Disable SW SMI Timer
+  //
+  SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);
+  IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);
+
+  //
+  // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+  //
+  Data8 = RTC_ADDRESS_REGISTER_D;
+  IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+  Data8 = 0x0;
+  IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);
+
+  //
+  // Enable SCI
+  //
+  Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+  Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;
+  IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+  //
+  // Do platform specific stuff for ACPI enable SMI
+  //
+
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SxSleepEntryCallBack (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  )
+/*++
+
+Routine Description:
+
+  Callback function entry for Sx sleep state.
+
+Arguments:
+
+  DispatchHandle   -  The handle of this callback, obtained when registering.
+  DispatchContext  -  The predefined context which contained sleep type and phase.
+
+Returns:
+
+  EFI_SUCCESS            -  Operation successfully performed.
+  EFI_INVALID_PARAMETER  -  Invalid parameter passed in.
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINT8       Data8;
+  UINT16      Data16;
+  UINT32      Data32;
+
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));
+
+  //
+  // Reget QNC power mgmr regs base in case of OS changing it at runtime
+  //
+  Status  = GetAllQncPmBase (gSmst);
+
+  //
+  // Clear RTC Alarm (if set)
+  //
+  Data8 = RTC_ADDRESS_REGISTER_C;
+  IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+  Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);
+
+  //
+  // Clear all ACPI status bits
+  //
+  Data32 = B_QNC_GPE0BLK_GPE0S_ALL;
+  Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );
+  Data16 = B_QNC_PM1BLK_PM1S_ALL;
+  Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );
+
+  //
+  // Handling S1 - setting appropriate wake bits in GPE0_EN
+  //
+  if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {
+    //
+    // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+    Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+    //
+    // Enable bit10 (RTC) in PM1E
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+    Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN
+  //
+  if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||
+      ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))
+     ) {
+    //
+    // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+    // Enable the WOL bits in GPE0_EN reg here for PME
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+    Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+    //
+    // Enable bit10 (RTC) in PM1E
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+    Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+  } else {
+
+    if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Status  = SaveRuntimeScriptTable (gSmst);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN
+    // Enable the WOL bits in GPE0_EN reg here for PME
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+    Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+    //
+    // Enable bit10 (RTC) in PM1E
+    //
+    Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+    Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+    Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+  }
+
+  //
+  // When entering a power-managed state like S3,
+  // PERST# must be asserted in advance of power-off.
+  //
+  PlatformPERSTAssert (mPlatformType);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetAllQncPmBase (
+  IN EFI_SMM_SYSTEM_TABLE2       *Smst
+  )
+/*++
+
+Routine Description:
+
+  Get QNC chipset LPC Power Management I/O Base at runtime.
+
+Arguments:
+
+  Smst  -  The standard SMM system table.
+
+Returns:
+
+  EFI_SUCCESS  -  Successfully init the device.
+  Other        -  Error occured whening calling Dxe lib functions.
+
+--*/
+{
+  mAcpiSmm.QncPmBase    = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_PM1BLK)) & B_QNC_LPC_PM1BLK_MASK;
+  mAcpiSmm.QncGpe0Base  = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_GPE0BLK)) & B_QNC_LPC_GPE0BLK_MASK;
+
+  //
+  // Quark does not support Changing Primary SoC IOBARs from what was
+  // setup in SEC/PEI UEFI stages.
+  //
+  ASSERT (mAcpiSmm.QncPmBase == (UINT32) PcdGet16 (PcdPm1blkIoBaseAddress));
+  ASSERT (mAcpiSmm.QncGpe0Base == (UINT32) PcdGet16 (PcdGpe0blkIoBaseAddress));
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+  IN EFI_SMM_SYSTEM_TABLE2       *Smst
+  )
+{
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;
+  UINT32                Data32;
+  UINT16                Data16;
+  UINT8                 Mask;
+  UINTN                 Index;
+  UINTN                 Offset;
+  UINT16                DeviceId;
+
+  //
+  // Check what Soc we are running on (read Host bridge DeviceId)
+  //
+  DeviceId = QncGetSocDeviceId();
+
+  //
+  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
+  // and vital to S3 resume. That's why we put save code here
+  //
+  Index = 0;
+  while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {
+
+    PciAddress.Bus              = mPciCfgRegTable[Index++];
+    PciAddress.Device           = mPciCfgRegTable[Index++];
+    PciAddress.Function         = mPciCfgRegTable[Index++];
+    PciAddress.Register         = 0;
+    PciAddress.ExtendedRegister = 0;
+
+    Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+    if (Data16 == 0xFFFF) {
+      Index += 8;
+      continue;
+    }
+
+    for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {
+
+      if (Mask == 0x00) {
+        Mask = 0x01;
+      }
+
+      if (mPciCfgRegTable[Index + Offset / 32] & Mask) {
+
+        PciAddress.Register = (UINT8) Offset;
+        Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+
+
+        //
+        // Save latest settings to runtime script table
+        //
+        S3BootScriptSavePciCfgWrite (
+             S3BootScriptWidthUint32,
+             PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),
+             1,
+             &Data32
+             );
+      }
+    }
+
+    Index += 8;
+
+  }
+
+  //
+  // Save message bus registers
+  //
+  Index = 0;
+  while (QNCS3SaveExtReg[Index] != 0xFF) {
+    Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+    //
+    // Save IMR settings with IMR protection disabled initially
+    // HMBOUND and IMRs will be locked just before jumping to the OS waking vector
+    //
+    if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+      if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+        Data32 &= ~IMR_LOCK;
+        if (DeviceId == QUARK2_MC_DEVICE_ID) {
+          Data32 &= ~IMR_EN;
+        }
+      }
+      if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+        Data32 = (UINT32)IMRX_ALL_ACCESS;
+      }
+    }
+
+    //
+    // Save latest settings to runtime script table
+    //
+    S3BootScriptSavePciCfgWrite (
+      S3BootScriptWidthUint32,
+      PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+      1,
+      &Data32
+     );
+
+    Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+    S3BootScriptSavePciCfgWrite (
+      S3BootScriptWidthUint32,
+      PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+      1,
+      &Data32
+     );
+    Index += 2;
+  }
+
+  Index = 0;
+  while (QNCS3SaveExtReg[Index] != 0xFF) {
+    //
+    // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)
+    //
+    if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+      if (DeviceId == QUARK2_MC_DEVICE_ID) {
+        if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+          Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+          Data32 &= ~IMR_LOCK;
+
+          //
+          // Save latest settings to runtime script table
+          //
+          S3BootScriptSavePciCfgWrite (
+            S3BootScriptWidthUint32,
+            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+            1,
+            &Data32
+          );
+
+          Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+          S3BootScriptSavePciCfgWrite (
+            S3BootScriptWidthUint32,
+            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+            1,
+            &Data32
+          );
+        }
+      } else {
+        if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+          Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+          //
+          // Save latest settings to runtime script table
+          //
+          S3BootScriptSavePciCfgWrite (
+            S3BootScriptWidthUint32,
+            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+            1,
+            &Data32
+          );
+
+          Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+          S3BootScriptSavePciCfgWrite (
+            S3BootScriptWidthUint32,
+            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+            1,
+            &Data32
+          );
+        }
+      }
+    }
+    Index += 2;
+  }
+
+  // Check if ECC scrub enabled and need re-enabling on resume
+  // All scrub related configuration registers are saved on suspend
+  // as part of QNCS3SaveExtReg configuration table script.
+  // The code below extends the S3 resume script with scrub reactivation
+  // message (if needed only)
+  Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);
+  if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {
+
+      Data32 = SCRUB_RESUME_MSG();
+
+      S3BootScriptSavePciCfgWrite (
+        S3BootScriptWidthUint32,
+        PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+        1,
+        &Data32
+       );
+  }
+
+  //
+  // Save I/O ports to S3 script table
+  //
+
+  //
+  // Important to trap Sx for SMM
+  //
+  Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+  S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);
+
+  return EFI_SUCCESS;
+}
+

+ 167 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h

@@ -0,0 +1,167 @@
+/** @file
+Header file for SMM S3 Handler Driver.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef _ACPI_SMM_DRIVER_H
+#define _ACPI_SMM_DRIVER_H
+//
+// Include files
+//
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/Spi.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Guid/Acpi.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/HobLib.h>
+#include <QNCAccess.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformPcieHelperLib.h>
+#include "Platform.h"
+#include <IndustryStandard/Pci22.h>
+
+#define EFI_ACPI_ACPI_ENABLE          0xA0
+#define EFI_ACPI_ACPI_DISABLE         0xA1
+
+#define R_IOPORT_CMOS_STANDARD_INDEX            0x70
+#define R_IOPORT_CMOS_STANDARD_DATA             0x71
+#define RTC_ADDRESS_REGISTER_C    12
+#define RTC_ADDRESS_REGISTER_D    13
+
+#define PCI_DEVICE(Bus, Dev, Func)  \
+          Bus, Dev, Func
+
+#define PCI_REG_MASK(Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7) \
+          Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7
+
+#define PCI_DEVICE_END    0xFF
+
+//
+// Related data structures definition
+//
+typedef struct _EFI_ACPI_SMM_DEV {
+
+  //
+  // Parent dispatch driver returned sleep handle
+  //
+  EFI_HANDLE  S3SleepEntryHandle;
+
+  EFI_HANDLE  S4SleepEntryHandle;
+
+  EFI_HANDLE  S1SleepEntryHandle;
+
+  EFI_HANDLE  S5SoftOffEntryHandle;
+
+  EFI_HANDLE  EnableAcpiHandle;
+
+  EFI_HANDLE  DisableAcpiHandle;
+
+  EFI_HANDLE  PpCallbackHandle;
+
+  EFI_HANDLE  MorCallbackHandle;
+
+  //
+  // QNC Power Management I/O register base
+  //
+  UINT32      QncPmBase;
+
+  //
+  // QNC General Purpose Event0 register base
+  //
+  UINT32      QncGpe0Base;
+
+  UINT32      BootScriptSaved;
+
+} EFI_ACPI_SMM_DEV;
+
+//
+// Prototypes
+//
+EFI_STATUS
+InitPlatformAcpiSmm (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable,
+  IN  OUT VOID            *CommBuffer,
+  IN  OUT UINTN           *CommBufferSize
+  );
+
+EFI_STATUS
+SxSleepEntryCallBack (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  );
+
+EFI_STATUS
+DisableAcpiCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  );
+
+EFI_STATUS
+EnableAcpiCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  );
+
+EFI_STATUS
+RegisterToDispatchDriver (
+  VOID
+  );
+
+EFI_STATUS
+GetAllQncPmBase (
+  IN EFI_SMM_SYSTEM_TABLE2       *Smst
+  );
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+  IN EFI_SMM_SYSTEM_TABLE2       *Smst
+  );
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+  IN  EFI_HANDLE                    DispatchHandle,
+  IN  CONST VOID                    *DispatchContext,
+  IN  OUT VOID                      *CommBuffer,
+  IN  OUT UINTN                     *CommBufferSize
+  );
+
+extern EFI_GUID gQncS3CodeInLockBoxGuid;
+extern EFI_GUID gQncS3ContextInLockBoxGuid;
+
+#endif

+ 78 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf

@@ -0,0 +1,78 @@
+## @file
+# Component description file for ACPI SMM Platform handler module
+#
+# This is QNC Smm platform driver .
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+  INF_VERSION                 = 0x00010005
+  BASE_NAME                   = AcpiSmmPlatform
+  FILE_GUID                   = F5AC7057-5650-466e-B692-76A47223EFB0
+  MODULE_TYPE                 = DXE_SMM_DRIVER
+  VERSION_STRING              = 1.0
+  PI_SPECIFICATION_VERSION    = 0x0001000A
+  ENTRY_POINT                 = InitAcpiSmmPlatform
+
+[Sources]
+  AcpiSmmPlatform.c
+  AcpiSmmPlatform.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  IntelFrameworkPkg/IntelFrameworkPkg.dec
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  ReportStatusCodeLib
+  UefiDriverEntryPoint
+  DebugLib
+  IoLib
+  PciLib
+  BaseMemoryLib
+  BaseLib
+  SmmServicesTableLib
+  PcdLib
+  HobLib
+  S3BootScriptLib
+  LockBoxLib
+  PlatformHelperLib
+  IntelQNCLib
+  PlatformPcieHelperLib
+
+[Protocols]
+  gEfiSmmSxDispatch2ProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiVariableArchProtocolGuid
+  gEfiVariableWriteArchProtocolGuid
+  gEfiGlobalNvsAreaProtocolGuid
+  gEfiSmmSwDispatch2ProtocolGuid
+
+[Guids]
+  gEfiSmmPeiSmramMemoryReserveGuid
+  gQncS3CodeInLockBoxGuid
+  gQncS3ContextInLockBoxGuid
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdPlatformType
+  gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+
+[Depex]
+  gEfiSmmSxDispatch2ProtocolGuid AND
+  gEfiPciRootBridgeIoProtocolGuid AND
+  gEfiVariableArchProtocolGuid AND
+  gEfiVariableWriteArchProtocolGuid AND
+  gEfiGlobalNvsAreaProtocolGuid AND
+  gEfiQncS3SupportProtocolGuid

+ 372 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c

@@ -0,0 +1,372 @@
+/** @file
+
+Processor power management initialization code.
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+extern EFI_ACPI_SDT_PROTOCOL   *mAcpiSdt;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+
+extern EFI_GUID gPowerManagementAcpiTableStorageGuid;
+
+/**
+  This function is the entry of processor power management initialization code.
+  It initializes the processor's power management features based on the user
+  configurations and hardware capabilities.
+**/
+VOID
+PpmInit (
+  VOID
+  )
+{
+  //
+  // Processor Power Management Flags
+  //
+  mGlobalNvsAreaPtr->Cfgd = PcdGet32(PcdPpmFlags);
+
+  //
+  // Patch and publish power management related acpi tables
+  //
+  PpmPatchAndPublishAcpiTables();
+}
+
+/**
+  This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+  VOID
+  )
+{
+    //
+    // Patch FADT table to enable C2,C3
+    //
+  PpmPatchFadtTable();
+
+  //
+    // Load all the power management acpi tables and patch IST table
+    //
+    PpmLoadAndPatchPMTables();
+}
+
+/**
+  This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+  VOID
+  )
+{
+    EFI_STATUS                    Status;
+  EFI_ACPI_DESCRIPTION_HEADER   *Table;
+  EFI_ACPI_SDT_HEADER           *CurrentTable;
+  EFI_ACPI_TABLE_VERSION        Version;
+  UINTN                         Index;
+  UINTN                         Handle;
+
+  //
+  // Scan all the acpi tables to find FADT 2.0
+  //
+  Index = 0;
+  do {
+    Status = mAcpiSdt->GetAcpiTable (
+                       Index,
+                       &CurrentTable,
+                       &Version,
+                       &Handle
+                       );
+    if (Status == EFI_NOT_FOUND) {
+      break;
+    }
+    ASSERT_EFI_ERROR (Status);
+    Index++;
+  } while (CurrentTable->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE || CurrentTable->Revision != 0x03);
+
+  ASSERT (CurrentTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
+
+  Table  = NULL;
+  Status = gBS->AllocatePool (EfiBootServicesData, CurrentTable->Length, (VOID **) &Table);
+  ASSERT (Table != NULL);
+  CopyMem (Table, CurrentTable, CurrentTable->Length);
+
+  //
+  // Update the ACPI table and recalculate checksum
+  //
+  Status = mAcpiTable->UninstallAcpiTable (mAcpiTable, Handle);
+  if (EFI_ERROR (Status)) {
+     //
+     // Should not get an error here ever, but abort if we do.
+     //
+     return ;
+  }
+
+  //
+  // Update the check sum
+  // It needs to be zeroed before the checksum calculation
+  //
+  ((EFI_ACPI_SDT_HEADER *)Table)->Checksum = 0;
+  ((EFI_ACPI_SDT_HEADER *)Table)->Checksum =
+    CalculateCheckSum8 ((VOID *)Table, Table->Length);
+
+  //
+  // Add the table
+  //
+  Status = mAcpiTable->InstallAcpiTable (
+                            mAcpiTable,
+                            Table,
+                            Table->Length,
+                            &Handle
+                            );
+  ASSERT_EFI_ERROR (Status);
+  gBS->FreePool (Table);
+}
+
+VOID
+SsdtTableUpdate (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
+  )
+/*++
+
+  Routine Description:
+
+    Update the SSDT table
+
+  Arguments:
+
+    Table   - The SSDT table to be patched
+
+  Returns:
+
+    None
+
+--*/
+{
+  UINT8      *CurrPtr;
+  UINT8      *SsdtPointer;
+  UINT32     *Signature;
+
+  //
+  // Loop through the ASL looking for values that we must fix up.
+  //
+  CurrPtr = (UINT8 *) TableHeader;
+  for (SsdtPointer = CurrPtr;
+       SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+       SsdtPointer++
+      )
+  {
+    Signature = (UINT32 *) SsdtPointer;
+    if ((*Signature) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
+      switch (*(Signature+1)) {
+      case (SIGNATURE_32 ('L', 'V', 'L', '0')):
+        Signature[0] = PcdGet16(PcdPmbaIoBaseAddress);
+        Signature[1] = 0;
+        break;
+      case (SIGNATURE_32 ('L', 'V', 'L', '2')):
+        Signature[0] = PcdGet16(PcdPmbaIoLVL2);
+        Signature[1] = 0;
+        break;
+      }
+    }
+  }
+}
+
+EFI_STATUS
+LocateSupportProtocol (
+  IN  EFI_GUID                       *Protocol,
+  OUT VOID                           **Instance,
+  IN  UINT32                         Type
+  )
+/*++
+
+Routine Description:
+
+  Locate the first instance of a protocol.  If the protocol requested is an
+  FV protocol, then it will return the first FV that contains the ACPI table
+  storage file.
+
+Arguments:
+
+  Protocol      The protocol to find.
+  Instance      Return pointer to the first instance of the protocol
+
+Returns:
+
+  EFI_SUCCESS           The function completed successfully.
+  EFI_NOT_FOUND         The protocol could not be located.
+  EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
+
+--*/
+{
+  EFI_STATUS              Status;
+  EFI_HANDLE              *HandleBuffer;
+  UINTN                   NumberOfHandles;
+  EFI_FV_FILETYPE         FileType;
+  UINT32                  FvStatus;
+  EFI_FV_FILE_ATTRIBUTES  Attributes;
+  UINTN                   Size;
+  UINTN                   i;
+
+  FvStatus = 0;
+
+  //
+  // Locate protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   Protocol,
+                   NULL,
+                   &NumberOfHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status)) {
+
+    //
+    // Defined errors at this time are not found and out of resources.
+    //
+    return Status;
+  }
+
+
+
+  //
+  // Looking for FV with ACPI storage file
+  //
+
+  for (i = 0; i < NumberOfHandles; i++) {
+    //
+    // Get the protocol on this handle
+    // This should not fail because of LocateHandleBuffer
+    //
+    Status = gBS->HandleProtocol (
+                     HandleBuffer[i],
+                     Protocol,
+                     Instance
+                     );
+    ASSERT_EFI_ERROR (Status);
+
+    if (!Type) {
+      //
+      // Not looking for the FV protocol, so find the first instance of the
+      // protocol.  There should not be any errors because our handle buffer
+      // should always contain at least one or LocateHandleBuffer would have
+      // returned not found.
+      //
+      break;
+    }
+
+    //
+    // See if it has the ACPI storage file
+    //
+
+    Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
+                                                              &gPowerManagementAcpiTableStorageGuid,
+                                                              NULL,
+                                                              &Size,
+                                                              &FileType,
+                                                              &Attributes,
+                                                              &FvStatus
+                                                              );
+
+    //
+    // If we found it, then we are done
+    //
+    if (Status == EFI_SUCCESS) {
+      break;
+    }
+  }
+
+  //
+  // Our exit status is determined by the success of the previous operations
+  // If the protocol was found, Instance already points to it.
+  //
+
+  //
+  // Free any allocated buffers
+  //
+  gBS->FreePool (HandleBuffer);
+
+  return Status;
+}
+
+/**
+  This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+  VOID
+  )
+{
+    EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+    EFI_STATUS                    Status;
+    INTN                          Instance;
+  EFI_ACPI_COMMON_HEADER        *CurrentTable;
+  UINTN                         TableHandle;
+  UINT32                        FvStatus;
+  UINTN                         Size;
+
+    Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
+    if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Read tables from the storage file.
+  //
+  Instance = 0;
+  CurrentTable = NULL;
+
+  while (Status == EFI_SUCCESS) {
+
+    Status = FwVol->ReadSection (
+                      FwVol,
+                      &gPowerManagementAcpiTableStorageGuid,
+                      EFI_SECTION_RAW,
+                      Instance,
+                      (VOID**)&CurrentTable,
+                      &Size,
+                      &FvStatus
+                      );
+
+    if (!EFI_ERROR(Status)) {
+      SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable);
+
+      //
+      // Update the check sum
+      // It needs to be zeroed before the checksum calculation
+      //
+      ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+      ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = (UINT8)
+        CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+      //
+      // Add the table
+      //
+      TableHandle = 0;
+      Status = mAcpiTable->InstallAcpiTable (
+                              mAcpiTable,
+                              CurrentTable,
+                              CurrentTable->Length,
+                              &TableHandle
+                              );
+
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Increment the instance
+      //
+      Instance++;
+      CurrentTable = NULL;
+    }
+  }
+
+}

+ 150 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h

@@ -0,0 +1,150 @@
+/** @file
+
+Processor power management initialization code.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef _PPM_H
+#define _PPM_H
+
+//
+// Bit definitions of PPMFlags
+//
+#define PPM_GV3         (1 << 0)  // Geyserville 3
+#define PPM_TURBO       (1 << 1)  // Turbo Mode
+#define PPM_SUPER_LFM   (1 << 2)  // N/2 Ratio
+#define PPM_C1          (1 << 4)  // C1 Capable, Enabled
+#define PPM_C2          (1 << 5)  // C2 Capable, Enabled
+#define PPM_C3          (1 << 6)  // C3 Capable, Enabled
+#define PPM_C4          (1 << 7)  // C4 Capable, Enabled
+#define PPM_C5          (1 << 8)  // C5/Deep C4 Capable, Enabled
+#define PPM_C6          (1 << 9)  // C6 Capable, Enabled
+#define PPM_C1E         (1 << 10) // C1E Enabled
+#define PPM_C2E         (1 << 11) // C2E Enabled
+#define PPM_C3E         (1 << 12) // C3E Enabled
+#define PPM_C4E         (1 << 13) // C4E Enabled
+#define PPM_HARD_C4E    (1 << 14) // Hard C4E Capable, Enabled
+#define PPM_TM1         (1 << 16) // Thermal Monitor 1
+#define PPM_TM2         (1 << 17) // Thermal Monitor 2
+#define PPM_PHOT        (1 << 19) // Bi-directional ProcHot
+#define PPM_MWAIT_EXT   (1 << 21) // MWAIT extensions supported
+#define PPM_CMP         (1 << 24) // CMP supported, Enabled
+#define PPM_TSTATE      (1 << 28) // CPU T states supported
+
+#define PPM_C_STATES    (PPM_C1 + PPM_C2 + PPM_C3 + PPM_C4 + PPM_C5 + PPM_C6)
+#define PPM_CE_STATES   (PPM_C1E + PPM_C2E + PPM_C3E + PPM_C4E + PPM_HARD_C4E)
+
+
+#define MAX_P_STATES_NUM    12
+
+#define AML_NAME_OP         0x08
+#define AML_SCOPE_OP        0x10
+#define AML_PACKAGE_OP      0x12
+#define AML_METHOD_OP       0x14
+
+#define S3_CPU_REGISTER_TABLE_GUID \
+  { \
+    0xc4ef988d, 0xe5e, 0x4403, { 0xbe, 0xeb, 0xf1, 0xbb, 0x6, 0x79, 0x6e, 0xdf } \
+  }
+
+#pragma pack(1)
+typedef struct {
+  UINT8   StartByte;
+  UINT32  NameStr;
+  UINT8   OpCode;
+  UINT16  Size;                // Hardcode to 16bit width because the table we use is fixed size
+  UINT8   NumEntries;
+} EFI_ACPI_NAME_COMMAND;
+
+typedef struct {
+  UINT8   PackageOp;
+  UINT8   PkgLeadByte;
+  UINT8   NumEntries;
+  UINT8   DwordPrefix0;
+  UINT32  CoreFreq;
+  UINT8   DwordPrefix1;
+  UINT32  Power;
+  UINT8   DwordPrefix2;
+  UINT32  TransLatency;
+  UINT8   DwordPrefix3;
+  UINT32  BMLatency;
+  UINT8   DwordPrefix4;
+  UINT32  Control;
+  UINT8   DwordPrefix5;
+  UINT32  Status;
+} EFI_PSS_PACKAGE;
+#pragma pack()
+
+typedef struct {
+  UINT32  Index;
+  UINT64  Value;
+} S3_CPU_REGISTER;
+
+//
+// Function prototypes
+//
+
+/**
+  This function is the entry of processor power management initialization code.
+  It initializes the processor's power management features based on the user
+  configurations and hardware capablities.
+**/
+VOID
+PpmInit (
+  VOID
+  );
+
+/**
+  This function is to determine the Processor Power Management Flags
+  based on the hardware capability.
+**/
+VOID
+PpmDetectCapability (
+  VOID
+  );
+
+/**
+  This function is to determine the user configuration mask
+**/
+VOID
+PpmGetUserConfigurationMask (
+  VOID
+  );
+
+/**
+  This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+  VOID
+  );
+
+/**
+  This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+  VOID
+  );
+
+/**
+  This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+  VOID
+  );
+
+/**
+  This function is to save cpu registers for s3 resume.
+**/
+VOID
+PpmS3SaveRegisters (
+  VOID
+  );
+#endif

+ 113 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c

@@ -0,0 +1,113 @@
+/** @file
+
+This is QNC Smm Power Management driver
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+EFI_SMM_CPU_PROTOCOL                    *mSmmCpu = NULL;
+EFI_GLOBAL_NVS_AREA                     *mGlobalNvsAreaPtr = NULL;
+EFI_MP_SERVICES_PROTOCOL                *mMpService = NULL;
+EFI_ACPI_SDT_PROTOCOL                   *mAcpiSdt = NULL;
+EFI_ACPI_TABLE_PROTOCOL                 *mAcpiTable = NULL;
+
+EFI_GUID    mS3CpuRegisterTableGuid = S3_CPU_REGISTER_TABLE_GUID;
+
+EFI_STATUS
+EFIAPI
+InitializePowerManagement (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+/*++
+
+Routine Description:
+
+  Initializes the SMM Handler Driver
+
+Arguments:
+
+  ImageHandle -
+
+  SystemTable -
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_STATUS                                Status;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL             *SwDispatch;
+  EFI_GLOBAL_NVS_AREA_PROTOCOL              *GlobalNvsAreaProtocol;
+
+  //
+  // Get SMM CPU protocol
+  //
+  Status = gSmst->SmmLocateProtocol (
+                    &gEfiSmmCpuProtocolGuid,
+                    NULL,
+                    (VOID **)&mSmmCpu
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  //  Get the Sw dispatch protocol
+  //
+  Status = gSmst->SmmLocateProtocol (
+                    &gEfiSmmSwDispatch2ProtocolGuid,
+                    NULL,
+                    (VOID**)&SwDispatch
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get Global NVS Area Protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **)&GlobalNvsAreaProtocol);
+  ASSERT_EFI_ERROR (Status);
+  mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+
+  //
+  // Locate and cache PI AcpiSdt Protocol.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiSdtProtocolGuid,
+                  NULL,
+                  (VOID **) &mAcpiSdt
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+
+  //
+  // Locate and cache PI AcpiSdt Protocol.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID **) &mAcpiTable
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+
+  //
+  // Get MpService protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Initialize power management features on processors
+  //
+  PpmInit();
+
+  return Status;
+}

+ 52 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h

@@ -0,0 +1,52 @@
+/** @file
+Header file for  QNC Smm Power Management driver
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_POWER_MANAGEMENT_H_
+#define _SMM_POWER_MANAGEMENT_H_
+
+#include <PiSmm.h>
+#include <IntelQNCDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/MpService.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+#include <AcpiCpuData.h>
+
+#include "Ppm.h"
+
+//
+// Module global variable
+//
+extern EFI_SMM_CPU_PROTOCOL                    *mSmmCpu;
+extern EFI_GLOBAL_NVS_AREA                     *mGlobalNvsAreaPtr;
+extern EFI_MP_SERVICES_PROTOCOL                *mMpService;
+
+//
+// Function prototypes
+//
+
+#endif

+ 74 - 0
Platform/Intel/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf

@@ -0,0 +1,74 @@
+## @file
+# Component description file for SMM Power Management module
+#
+# This is QNC Smm Power Management driver .
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmPowerManagement
+  FILE_GUID                      = 271F1343-20D6-4e14-9B62-3C0297F56F07
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = InitializePowerManagement
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  SmmPowerManagement.c
+  SmmPowerManagement.h
+  Ppm.c
+  Ppm.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DebugLib
+  PcdLib
+  IoLib
+  PciLib
+  BaseLib
+  BaseMemoryLib
+  SmmServicesTableLib
+  UefiBootServicesTableLib
+  S3BootScriptLib
+  MemoryAllocationLib
+
+[Protocols]
+  gEfiSmmCpuProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED
+  gEfiSmmSwDispatch2ProtocolGuid                # PROTOCOL ALWAYS_CONSUMED
+  gEfiGlobalNvsAreaProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED
+  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL ALWAYS_CONSUMED
+  gEfiMpServiceProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiAcpiSdtProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+
+[Guids]
+  gPowerManagementAcpiTableStorageGuid
+
+[Pcd]
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoLVL2
+  gQuarkPlatformTokenSpaceGuid.PcdPpmFlags
+
+[Depex]
+  gEfiSmmCpuProtocolGuid AND
+  gEfiSmmSwDispatch2ProtocolGuid AND
+  gEfiGlobalNvsAreaProtocolGuid AND
+  gEfiAcpiTableProtocolGuid AND
+  gEfiMpServiceProtocolGuid

+ 47 - 0
Platform/Intel/QuarkPlatformPkg/Application/ForceRecovery/ForceRecovery.c

@@ -0,0 +1,47 @@
+/** @file
+  Application that sets a sticky bit to force recovery on next reset.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/QNCAccessLib.h>
+
+/**
+  The user Entry Point for Application. The user code starts with this function
+  as the real entry point for the application.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  //
+  // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
+  //
+  QNCAltPortWrite (
+    QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
+    QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,
+    QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY
+    );
+
+  //
+  // Do a warm reset
+  //
+  gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+
+  return EFI_SUCCESS;
+}

+ 34 - 0
Platform/Intel/QuarkPlatformPkg/Application/ForceRecovery/ForceRecovery.inf

@@ -0,0 +1,34 @@
+## @file
+#  Application that sets a sticky bit to force recovery on next reset.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ForceRecovery
+  FILE_GUID                      = 3A61FD45-69A0-42AD-B261-24DA451BF442
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  ForceRecovery.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+
+[LibraryClasses]
+  UefiApplicationEntryPoint
+  UefiRuntimeServicesTableLib
+  QNCAccessLib

+ 262 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c

@@ -0,0 +1,262 @@
+/** @file
+  Platform Flash Access library.
+
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX        0
+#define SPI_OPCODE_READ_ID_INDEX         1
+#define SPI_OPCODE_WRITE_S_INDEX         2
+#define SPI_OPCODE_WRITE_INDEX           3
+#define SPI_OPCODE_READ_INDEX            4
+#define SPI_OPCODE_ERASE_INDEX           5
+#define SPI_OPCODE_READ_S_INDEX          6
+#define SPI_OPCODE_CHIP_ERASE_INDEX      7
+
+#define SPI_ERASE_SECTOR_SIZE            SIZE_4KB  //This is the chipset requirement
+
+STATIC EFI_PHYSICAL_ADDRESS     mInternalFdAddress;
+EFI_SPI_PROTOCOL                *mSpiProtocol;
+
+/**
+  Writes specified number of bytes from the input buffer to the address
+
+  @param[in]      WriteAddress  The flash address to be written.
+  @param[in, out] NumBytes      The number of bytes.
+  @param[in]      Buffer        The data buffer to be written.
+
+  @return The status of flash write.
+**/
+EFI_STATUS
+FlashFdWrite (
+  IN  UINTN                               WriteAddress,
+  IN OUT UINTN                            *NumBytes,
+  IN  UINT8                               *Buffer
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  Status = mSpiProtocol->Execute (
+                           mSpiProtocol,
+                           SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+                           0,                      // PrefixOpcodeIndex
+                           TRUE,                   // DataCycle
+                           TRUE,                   // Atomic
+                           TRUE,                   // ShiftOut
+                           WriteAddress,           // Address
+                           (UINT32) (*NumBytes),   // Data Number
+                           Buffer,
+                           EnumSpiRegionBios
+                           );
+  DEBUG((DEBUG_INFO, "FlashFdWrite - 0x%x - %r\n", (UINTN)WriteAddress, Status));
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+/**
+  Erase a certain block from address LbaWriteAddress
+
+  @param[in] WriteAddress  The flash address to be erased.
+
+  @return The status of flash erase.
+**/
+EFI_STATUS
+FlashFdErase (
+  IN UINTN                                WriteAddress
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = mSpiProtocol->Execute (
+                           mSpiProtocol,
+                           SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
+                           0,                      // PrefixOpcodeIndex
+                           FALSE,                  // DataCycle
+                           TRUE,                   // Atomic
+                           FALSE,                  // ShiftOut
+                           WriteAddress,           // Address
+                           0,                      // Data Number
+                           NULL,
+                           EnumSpiRegionBios       // SPI_REGION_TYPE
+                           );
+  DEBUG((DEBUG_INFO, "FlashFdErase - 0x%x - %r\n", (UINTN)WriteAddress, Status));
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+/**
+  Perform flash write operation with progress indicator.  The start and end
+  completion percentage values are passed into this function.  If the requested
+  flash write operation is broken up, then completion percentage between the
+  start and end values may be passed to the provided Progress function.  The
+  caller of this function is required to call the Progress function for the
+  start and end completion percentage values.  This allows the Progress,
+  StartPercentage, and EndPercentage parameters to be ignored if the requested
+  flash write operation can not be broken up
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+  @param[in] Progress          A function used report the progress of the
+                               firmware update.  This is an optional parameter
+                               that may be NULL.
+  @param[in] StartPercentage   The start completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+  @param[in] EndPercentage     The end completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWriteWithProgress (
+  IN PLATFORM_FIRMWARE_TYPE                         FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS                           FlashAddress,
+  IN FLASH_ADDRESS_TYPE                             FlashAddressType,
+  IN VOID                                           *Buffer,
+  IN UINTN                                          Length,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,        OPTIONAL
+  IN UINTN                                          StartPercentage,
+  IN UINTN                                          EndPercentage
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               SectorNum;
+  UINTN               Index;
+  UINTN               NumBytes;
+
+  DEBUG((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FlashAddressType == FlashAddressTypeAbsoluteAddress) {
+    FlashAddress = FlashAddress - mInternalFdAddress;
+  }
+
+  //
+  // Erase & Write
+  //
+  SectorNum = Length / SPI_ERASE_SECTOR_SIZE;
+  for (Index = 0; Index < SectorNum; Index++){
+    if (Progress != NULL) {
+      Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / SectorNum));
+    }
+
+    if (CompareMem(
+          (UINT8 *)(UINTN)(FlashAddress + mInternalFdAddress) + Index * SPI_ERASE_SECTOR_SIZE,
+          (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE,
+          SPI_ERASE_SECTOR_SIZE) == 0) {
+      DEBUG((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));
+      continue;
+    }
+    DEBUG((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));
+
+    Status = FlashFdErase (
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE
+               );
+    if (Status != EFI_SUCCESS){
+      break;
+    }
+    NumBytes = SPI_ERASE_SECTOR_SIZE;
+    Status = FlashFdWrite (
+               (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE,
+               &NumBytes,
+               (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE
+               );
+    if (Status != EFI_SUCCESS){
+      break;
+    }
+  }
+  if (Progress != NULL) {
+    Progress (EndPercentage);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Perform flash write operation.
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite (
+  IN PLATFORM_FIRMWARE_TYPE       FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS         FlashAddress,
+  IN FLASH_ADDRESS_TYPE           FlashAddressType,
+  IN VOID                         *Buffer,
+  IN UINTN                        Length
+  )
+{
+  return PerformFlashWriteWithProgress (
+           FirmwareType,
+           FlashAddress,
+           FlashAddressType,
+           Buffer,
+           Length,
+           NULL,
+           0,
+           0
+           );
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the EFI image.
+  @param[in]  SystemTable       A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS  Constructor returns successfully.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32(PcdFlashAreaBaseAddress);
+  DEBUG((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  Status = gBS->LocateProtocol(&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);
+  ASSERT_EFI_ERROR(Status);
+
+  return EFI_SUCCESS;
+}

+ 47 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.inf

@@ -0,0 +1,47 @@
+## @file
+#  Platform Flash Access library.
+#
+#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLibDxe
+  FILE_GUID                      = 9168384A-5F66-4CF7-AEB6-845BDEBD3012
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib|DXE_DRIVER DXE_RUNTIME_DRIVER
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PlatformFlashAccessLibDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  DebugLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEfiSpiProtocolGuid
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+
+[Depex]
+  gEfiSpiProtocolGuid

+ 330 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.c

@@ -0,0 +1,330 @@
+/** @file
+  SPI flash device description.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include "SpiFlashDevice.h"
+
+#define FLASH_SIZE  (FixedPcdGet32 (PcdFlashAreaSize))
+
+SPI_INIT_TABLE  mSpiInitTable[] = {
+  //
+  // Macronix 32Mbit part
+  //
+  {
+    SPI_MX25L3205_ID1,
+    SPI_MX25L3205_ID2,
+    SPI_MX25L3205_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle20MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 32Mbit part
+  //
+  {
+    SPI_W25X32_ID1,
+    SF_DEVICE_ID0_W25QXX,
+    SF_DEVICE_ID1_W25Q32,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 32Mbit part
+  //
+  {
+    SPI_W25X32_ID1,
+    SPI_W25X32_ID2,
+    SPI_W25X32_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle33MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Atmel 32Mbit part
+  //
+  {
+    SPI_AT26DF321_ID1,
+    SPI_AT26DF321_ID2,  // issue: byte 2 identifies family/density for Atmel
+    SPI_AT26DF321_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    (UINTN)(0x400000 - FLASH_SIZE), // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Intel 32Mbit part bottom boot
+  //
+  {
+    SPI_QH25F320_ID1,
+    SPI_QH25F320_ID2,
+    SPI_QH25F320_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_ENABLE
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    0,           // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // SST 64Mbit part
+  //
+  {
+    SPI_SST25VF080B_ID1,      // VendorId
+    SF_DEVICE_ID0_25VF064C,   // DeviceId 0
+    SF_DEVICE_ID1_25VF064C,   // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // NUMONYX 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_NUMONYX,     // VendorId
+    SF_DEVICE_ID0_M25PX64,    // DeviceId 0
+    SF_DEVICE_ID1_M25PX64,    // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Atmel 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_ATMEL,       // VendorId
+    SF_DEVICE_ID0_AT25DF641,  // DeviceId 0
+    SF_DEVICE_ID1_AT25DF641,  // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Spansion 64Mbit part
+  //
+  {
+    SF_VENDOR_ID_SPANSION,       // VendorId
+    SF_DEVICE_ID0_S25FL064K,  // DeviceId 0
+    SF_DEVICE_ID1_S25FL064K,  // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+
+  //
+  // Macronix 64Mbit part bottom boot
+  //
+  {
+    SF_VENDOR_ID_MX,          // VendorId
+    SF_DEVICE_ID0_25L6405D,   // DeviceId 0
+    SF_DEVICE_ID1_25L6405D,   // DeviceId 1
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 64Mbit part bottom boot
+  //
+  {
+    SPI_W25X64_ID1,
+    SF_DEVICE_ID0_W25QXX,
+    SF_DEVICE_ID1_W25Q64,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Winbond 64Mbit part bottom boot
+  //
+  {
+    SPI_W25X64_ID1,
+    SPI_W25X64_ID2,
+    SPI_W25X64_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle50MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle50MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle50MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle50MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_ERASE,       EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle50MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle50MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  },
+  //
+  // Intel 64Mbit part bottom boot
+  //
+  {
+    SPI_QH25F640_ID1,
+    SPI_QH25F640_ID2,
+    SPI_QH25F640_ID3,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_JEDEC_ID,    EnumSpiCycle33MHz, EnumSpiOperationJedecId},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ_ID,     EnumSpiCycle33MHz, EnumSpiOperationOther},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_WRITE_S,     EnumSpiCycle33MHz, EnumSpiOperationWriteStatus},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_WRITE,       EnumSpiCycle33MHz, EnumSpiOperationProgramData_1_Byte},
+      {EnumSpiOpcodeRead,        SPI_COMMAND_READ,        EnumSpiCycle33MHz, EnumSpiOperationReadData},
+      {EnumSpiOpcodeWrite,       SPI_COMMAND_BLOCK_ERASE, EnumSpiCycle33MHz, EnumSpiOperationErase_64K_Byte},
+      {EnumSpiOpcodeReadNoAddr,  SPI_COMMAND_READ_S,      EnumSpiCycle33MHz, EnumSpiOperationReadStatus},
+      {EnumSpiOpcodeWriteNoAddr, SPI_COMMAND_CHIP_ERASE,  EnumSpiCycle33MHz, EnumSpiOperationFullChipErase}
+    },
+    0x800000 - FLASH_SIZE,          // BIOS Start Offset
+    FLASH_SIZE   // BIOS image size in flash
+  }
+};

+ 180 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/SpiFlashDevice.h

@@ -0,0 +1,180 @@
+/** @file
+  SPI flash device header file.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SPI_FLASH_DEVICE_H_
+#define _SPI_FLASH_DEVICE_H_
+
+#include <PiDxe.h>
+#include <Protocol/Spi.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+//
+// Supported SPI Flash Devices
+//
+typedef enum {
+  EnumSpiFlash25L3205D,   // Macronix 32Mbit part
+  EnumSpiFlashW25Q32,     // Winbond 32Mbit part
+  EnumSpiFlashW25X32,     // Winbond 32Mbit part
+  EnumSpiFlashAT25DF321,  // Atmel 32Mbit part
+  EnumSpiFlashQH25F320,   // Intel 32Mbit part
+  EnumSpiFlash25VF064C,   // SST 64Mbit part
+  EnumSpiFlashM25PX64,    // NUMONYX 64Mbit part
+  EnumSpiFlashAT25DF641,  // Atmel 64Mbit part
+  EnumSpiFlashS25FL064K,  // Spansion 64Mbit part
+  EnumSpiFlash25L6405D,   // Macronix 64Mbit part
+  EnumSpiFlashW25Q64,     // Winbond 64Mbit part
+  EnumSpiFlashW25X64,     // Winbond 64Mbit part
+  EnumSpiFlashQH25F640,   // Intel 64Mbit part
+  EnumSpiFlashMax
+} SPI_FLASH_TYPES_SUPPORTED;
+
+//
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE                 0x02
+#define SPI_COMMAND_WRITE_AAI             0xAD
+#define SPI_COMMAND_READ                  0x03
+#define SPI_COMMAND_ERASE                 0x20
+#define SPI_COMMAND_WRITE_DISABLE         0x04
+#define SPI_COMMAND_READ_S                0x05
+#define SPI_COMMAND_WRITE_ENABLE          0x06
+#define SPI_COMMAND_READ_ID               0xAB
+#define SPI_COMMAND_JEDEC_ID              0x9F
+#define SPI_COMMAND_WRITE_S_EN            0x50
+#define SPI_COMMAND_WRITE_S               0x01
+#define SPI_COMMAND_CHIP_ERASE            0xC7
+#define SPI_COMMAND_BLOCK_ERASE           0xD8
+
+//
+// Flash JEDEC device ids
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1               0xBF
+#define SPI_SST25VF080B_ID2               0x25
+#define SPI_SST25VF080B_ID3               0x8E
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1               0xBF
+#define SPI_SST25VF016B_ID2               0x25
+#define SPI_SST25V016BF_ID3               0x41
+//
+// Macronix 32Mbit part
+//
+// MX25 part does not support WRITE_AAI comand (0xAD)
+//
+#define SPI_MX25L3205_ID1                 0xC2
+#define SPI_MX25L3205_ID2                 0x20
+#define SPI_MX25L3205_ID3                 0x16
+//
+// Intel 32Mbit part bottom boot
+//
+#define SPI_QH25F320_ID1                  0x89
+#define SPI_QH25F320_ID2                  0x89
+#define SPI_QH25F320_ID3                  0x12  // 32Mbit bottom boot
+//
+// Intel 64Mbit part bottom boot
+//
+#define SPI_QH25F640_ID1                  0x89
+#define SPI_QH25F640_ID2                  0x89
+#define SPI_QH25F640_ID3                  0x13  // 64Mbit bottom boot
+//
+// QH part does not support command 0x20 for erase; only 0xD8 (sector erase)
+// QH part has 0x40 command for erase of parameter block (8 x 8K blocks at bottom of part)
+// 0x40 command ignored if address outside of parameter block range
+//
+#define SPI_QH25F320_COMMAND_PBLOCK_ERASE 0x40
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1                    0xEF
+#define SPI_W25X32_ID2                    0x30  // Memory Type
+#define SPI_W25X32_ID3                    0x16  // Capacity
+#define SF_DEVICE_ID1_W25Q32              0x16
+
+//
+// Winbond 64Mbit part
+//
+#define SPI_W25X64_ID1                    0xEF
+#define SPI_W25X64_ID2                    0x30  // Memory Type
+#define SPI_W25X64_ID3                    0x17  // Capacity
+#define SF_DEVICE_ID0_W25QXX              0x40
+#define SF_DEVICE_ID1_W25Q64              0x17
+//
+// Winbond 128Mbit part
+//
+#define SF_DEVICE_ID0_W25Q128             0x40
+#define SF_DEVICE_ID1_W25Q128             0x18
+
+//
+// Atmel 32Mbit part
+//
+#define SPI_AT26DF321_ID1                 0x1F
+#define SPI_AT26DF321_ID2                 0x47  // [7:5]=Family, [4:0]=Density
+#define SPI_AT26DF321_ID3                 0x00
+
+#define SF_VENDOR_ID_ATMEL                0x1F
+#define SF_DEVICE_ID0_AT25DF641           0x48
+#define SF_DEVICE_ID1_AT25DF641           0x00
+
+//
+// SST 8Mbit part
+//
+#define SPI_SST25VF080B_ID1               0xBF
+#define SPI_SST25VF080B_ID2               0x25
+#define SPI_SST25VF080B_ID3               0x8E
+#define SF_DEVICE_ID0_25VF064C            0x25
+#define SF_DEVICE_ID1_25VF064C            0x4B
+
+//
+// SST 16Mbit part
+//
+#define SPI_SST25VF016B_ID1               0xBF
+#define SPI_SST25VF016B_ID2               0x25
+#define SPI_SST25V016BF_ID3               0x41
+
+//
+// Winbond 32Mbit part
+//
+#define SPI_W25X32_ID1                    0xEF
+#define SPI_W25X32_ID2                    0x30  // Memory Type
+#define SPI_W25X32_ID3                    0x16  // Capacity
+
+#define  SF_VENDOR_ID_MX             0xC2
+#define  SF_DEVICE_ID0_25L6405D      0x20
+#define  SF_DEVICE_ID1_25L6405D      0x17
+
+#define  SF_VENDOR_ID_NUMONYX        0x20
+#define  SF_DEVICE_ID0_M25PX64       0x71
+#define  SF_DEVICE_ID1_M25PX64       0x17
+
+//
+// Spansion 64Mbit part
+//
+#define SF_VENDOR_ID_SPANSION             0xEF
+#define SF_DEVICE_ID0_S25FL064K           0x40
+#define SF_DEVICE_ID1_S25FL064K           0x00
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX                    0   // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX                    1   // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL                         0xDC
+
+#define PFAB_CARD_DEVICE_ID               0x5150
+#define PFAB_CARD_VENDOR_ID               0x8086
+#define PFAB_CARD_SETUP_REGISTER          0x40
+#define PFAB_CARD_SETUP_BYTE              0x0d
+
+
+#endif

+ 83 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc

@@ -0,0 +1,83 @@
+/** @file
+  System Firmware descriptor.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#define PACKAGE_VERSION                     0xFFFFFFFF
+#define PACKAGE_VERSION_STRING              L"Unknown"
+
+#define CURRENT_FIRMWARE_VERSION            0x00000002
+#define CURRENT_FIRMWARE_VERSION_STRING     L"0x00000002"
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
+
+#define IMAGE_ID                            SIGNATURE_64('Q', 'U', 'A', 'R', 'K', '_', 'F', 'd')
+#define IMAGE_ID_STRING                     L"QuarkPlatformFd"
+
+// PcdSystemFmpCapsuleImageTypeIdGuid
+#define IMAGE_TYPE_ID_GUID                  { 0x62af20c0, 0x7016, 0x424a, { 0x9b, 0xf8, 0x9c, 0xcc, 0x86, 0x58, 0x40, 0x90 } }
+
+typedef struct {
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
+  // real string data
+  CHAR16                                  ImageIdNameStr[sizeof(IMAGE_ID_STRING)/sizeof(CHAR16)];
+  CHAR16                                  VersionNameStr[sizeof(CURRENT_FIRMWARE_VERSION_STRING)/sizeof(CHAR16)];
+  CHAR16                                  PackageVersionNameStr[sizeof(PACKAGE_VERSION_STRING)/sizeof(CHAR16)];
+} IMAGE_DESCRIPTOR;
+
+IMAGE_DESCRIPTOR mImageDescriptor =
+{
+  {
+    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
+    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
+    sizeof(IMAGE_DESCRIPTOR),
+    PACKAGE_VERSION,                                       // PackageVersion
+    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   // PackageVersionName
+    1,                                                     // ImageIndex;
+    {0x0},                                                 // Reserved
+    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
+    IMAGE_ID,                                              // ImageId;
+    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          // ImageIdName;
+    CURRENT_FIRMWARE_VERSION,                              // Version;
+    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
+    {0x0},                                                 // Reserved2
+    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
+    0x0,                                                   // Compatibilities;
+    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     // LowestSupportedImageVersion;
+    0x00000000,                                            // LastAttemptVersion;
+    0,                                                     // LastAttemptStatus;
+    {0x0},                                                 // Reserved3
+    0,                                                     // HardwareInstance;
+  },
+  // real string data
+  {IMAGE_ID_STRING},
+  {CURRENT_FIRMWARE_VERSION_STRING},
+  {PACKAGE_VERSION_STRING},
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from
+  // removing the data structure from the executable
+  //
+  return (VOID*)&mImageDescriptor;
+}

+ 40 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf

@@ -0,0 +1,40 @@
+## @file
+#  System Firmware descriptor.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemFirmwareDescriptor
+  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemFirmwareDescriptorPeimEntry
+
+[Sources]
+  SystemFirmwareDescriptorPei.c
+  SystemFirmwareDescriptor.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  PeimEntryPoint
+
+[FixedPcd]
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize
+
+[Pcd]
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+
+[Depex]
+  TRUE

+ 60 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c

@@ -0,0 +1,60 @@
+/** @file
+  System Firmware descriptor producer.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Entrypoint for SystemFirmwareDescriptor PEIM.
+
+  @param[in]  FileHandle  Handle of the file being invoked.
+  @param[in]  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            PPI successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemFirmwareDescriptorPeimEntry (
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  EFI_STATUS                              Status;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
+  UINTN                                   Size;
+  UINTN                                   Index;
+  UINT32                                  AuthenticationStatus;
+
+  //
+  // Search RAW section.
+  //
+  Index = 0;
+  while (TRUE) {
+    Status = PeiServicesFfsFindSectionData3(EFI_SECTION_RAW, Index, FileHandle, (VOID **)&Descriptor, &AuthenticationStatus);
+    if (EFI_ERROR(Status)) {
+      // Should not happen, must something wrong in FDF.
+      ASSERT(FALSE);
+      return EFI_NOT_FOUND;
+    }
+    if (Descriptor->Signature == EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
+      break;
+    }
+    Index++;
+  }
+
+  DEBUG((DEBUG_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\n", Descriptor->Length));
+
+  Size = Descriptor->Length;
+  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
+
+  return EFI_SUCCESS;
+}

+ 57 - 0
Platform/Intel/QuarkPlatformPkg/Feature/Capsule/SystemFirmwareUpdateConfig/SystemFirmwareUpdateConfig.ini

@@ -0,0 +1,57 @@
+## @file
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Head]
+NumOfUpdate = 4
+NumOfRecovery = 2
+Update0 = QuarkFvMain
+Update1 = QuarkFvBinary
+Update2 = QuarkFvRecovery
+Update3 = QuarkFvNvRam
+Recovery0 = QuarkFvMain
+Recovery1 = QuarkFvPayload
+
+[QuarkFvPayload]
+FirmwareType = 0            # SystemFirmware
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00400000    # Base address offset on flash
+Length      = 0x00100000    # Length
+ImageOffset = 0x00400000    # Image offset of this SystemFirmware image
+FileGuid    = 14D83A59-A810-4556-8192-1C0A593C065C  # PcdEdkiiSystemFirmwareFileGuid
+
+[QuarkFvMain]
+FirmwareType = 0            # SystemFirmware
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00500000    # Base address offset on flash
+Length      = 0x001E0000    # Length
+ImageOffset = 0x00500000    # Image offset of this SystemFirmware image
+FileGuid    = 14D83A59-A810-4556-8192-1C0A593C065C  # PcdEdkiiSystemFirmwareFileGuid
+
+[QuarkFvNvRam]
+FirmwareType = 1            # NvRam
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x006E0000    # Base address offset on flash
+Length      = 0x00020000    # Length
+ImageOffset = 0x006E0000    # Image offset of this SystemFirmware image
+FileGuid    = 14D83A59-A810-4556-8192-1C0A593C065C  # PcdEdkiiSystemFirmwareFileGuid
+
+[QuarkFvBinary]
+FirmwareType = 0            # SystemFirmware
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00700000    # Base address offset on flash
+Length      = 0x00010000    # Length
+ImageOffset = 0x00700000    # Image offset of this SystemFirmware image
+FileGuid    = 14D83A59-A810-4556-8192-1C0A593C065C  # PcdEdkiiSystemFirmwareFileGuid
+
+[QuarkFvRecovery]
+FirmwareType = 0            # SystemFirmware
+AddressType = 0             # 0 - relative address, 1 - absolute address.
+BaseAddress = 0x00710000    # Base address offset on flash
+Length      = 0x000F0000    # Length
+ImageOffset = 0x00710000    # Image offset of this SystemFirmware image
+FileGuid    = 14D83A59-A810-4556-8192-1C0A593C065C  # PcdEdkiiSystemFirmwareFileGuid
+

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnDataCD.h

@@ -0,0 +1,23 @@
+/** @file
+Capsule on Data CD GUID.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+This is the contract between the recovery module and device recovery module
+in order to convey the name of a given recovery module type
+
+**/
+
+#ifndef _CAPSULE_ON_DATA_CD_H
+#define _CAPSULE_ON_DATA_CD_H
+
+#define PEI_CAPSULE_ON_DATA_CD_GUID \
+  { \
+  0x5cac0099, 0x0dc9, 0x48e5, {0x80, 0x68, 0xbb, 0x95, 0xf5, 0x40, 0x0a, 0x9f } \
+  };
+
+extern EFI_GUID gPeiCapsuleOnDataCDGuid;
+
+#endif

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatFloppyDisk.h

@@ -0,0 +1,23 @@
+/** @file
+Capsule on Fat Floppy Disk GUID.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+This is the contract between the recovery module and device recovery module
+in order to convey the name of a given recovery module type
+
+**/
+
+#ifndef _CAPSULE_ON_FAT_FLOPPY_DISK_H
+#define _CAPSULE_ON_FAT_FLOPPY_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_FLOPPY_DISK_GUID \
+  { \
+  0x2e3d2e75, 0x9b2e, 0x412d, {0xb4, 0xb1, 0x70, 0x41, 0x6b, 0x87, 0x0, 0xff }\
+  };
+
+extern EFI_GUID gPeiCapsuleOnFatFloppyDiskGuid;
+
+#endif

+ 24 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatIdeDisk.h

@@ -0,0 +1,24 @@
+/** @file
+Capsule on Fat Ide Disk GUID.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+This is the contract between the recovery module and device recovery module
+in order to convey the name of a given recovery module type
+
+**/
+
+#ifndef _CAPSULE_ON_FAT_IDE_DISK_H
+#define _CAPSULE_ON_FAT_IDE_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_IDE_DISK_GUID \
+  { \
+  0xb38573b6, 0x6200, 0x4ac5, {0xb5, 0x1d, 0x82, 0xe6, 0x59, 0x38, 0xd7, 0x83 }\
+  };
+
+extern EFI_GUID gPeiCapsuleOnFatIdeDiskGuid;
+
+#endif

+ 24 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/CapsuleOnFatUsbDisk.h

@@ -0,0 +1,24 @@
+/** @file
+Capsule on Fat Usb Disk GUID.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+This is the contract between the recovery module and device recovery module
+in order to convey the name of a given recovery module type
+
+**/
+
+#ifndef _PEI_CAPSULE_ON_FAT_USB_DISK_H
+#define _PEI_CAPSULE_ON_FAT_USB_DISK_H
+
+#define PEI_CAPSULE_ON_FAT_USB_DISK_GUID \
+  { \
+  0x0ffbce19, 0x324c, 0x4690, {0xa0, 0x09, 0x98, 0xc6, 0xae, 0x2e, 0xb1, 0x86 } \
+  };
+
+extern EFI_GUID gPeiCapsuleOnFatUsbDiskGuid;
+
+#endif

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/MemoryConfigData.h

@@ -0,0 +1,23 @@
+/** @file
+Define a GUID name for GUID HOB which is used to pass Memory
+Configuration Data information to different modules.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MEMORY_CONFIG_DATA_H_
+#define _MEMORY_CONFIG_DATA_H_
+
+#define EFI_MEMORY_CONFIG_DATA_GUID \
+  { \
+    0x80dbd530, 0xb74c, 0x4f11, {0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31 } \
+  }
+
+#define EFI_MEMORY_CONFIG_DATA_NAME  L"MemoryConfig"
+
+extern EFI_GUID gEfiMemoryConfigDataGuid;
+
+#endif

+ 46 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/QuarkCapsuleGuid.h

@@ -0,0 +1,46 @@
+/** @file
+
+Capsule format guid for Quark capsule image.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _QUARK_CAPSULE_GUID_H_
+#define _QUARK_CAPSULE_GUID_H_
+
+#define QUARK_CAPSULE_GUID \
+  { 0xd400d1e4, 0xa314, 0x442b, { 0x89, 0xed, 0xa9, 0x2e, 0x4c, 0x81, 0x97, 0xcb } }
+
+#define SMI_INPUT_UPDATE_CAP 0x27
+#define SMI_INPUT_GET_CAP    0x28
+
+#define SMI_CAP_FUNCTION     0xEF
+
+#pragma pack(1)
+typedef struct {
+   UINT64  Address;
+   UINT32  BufferOffset;
+   UINT32  Size;
+   UINT32  Flags;
+   UINT32  Reserved;
+} CAPSULE_FRAGMENT;
+
+typedef struct {
+  UINTN         CapsuleLocation;  // Top of the capsule that point to structure CAPSULE_FRAGMENT
+  UINTN         CapsuleSize;    // Size of the capsule
+  EFI_STATUS   Status;      // Returned status
+} CAPSULE_INFO_PACKET;
+
+typedef struct {
+  UINTN           BlocksCompleted;  // # of blocks processed
+  UINTN           TotalBlocks;      // Total # of blocks to be processed
+  EFI_STATUS      Status;            // returned status
+} UPDATE_STATUS_PACKET;
+#pragma pack()
+
+extern EFI_GUID gEfiQuarkCapsuleGuid;
+
+#endif

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/QuarkVariableLock.h

@@ -0,0 +1,23 @@
+/** @file
+
+Guid and variable name used to trigger quark lock of specific UEFI variables.
+
+Copyright (c) 2013 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _QUARK_VARIABLE_LOCK_GUID_H_
+#define _QUARK_VARIABLE_LOCK_GUID_H_
+
+#define QUARK_VARIABLE_LOCK_GUID \
+  { \
+    0xeef749c2, 0xc047, 0x4d6e, { 0xb1, 0xbc, 0xd3, 0x6e, 0xb3, 0xa5, 0x55, 0x9c } \
+  }
+
+#define QUARK_VARIABLE_LOCK_NAME  L"QuarkVariableLock"
+
+extern EFI_GUID gQuarkVariableLockGuid;
+
+#endif

+ 29 - 0
Platform/Intel/QuarkPlatformPkg/Include/Guid/SystemNvDataHobGuid.h

@@ -0,0 +1,29 @@
+/** @file
+GUIDs used for System Non Volatile HOB entries in the in the HOB list and FV Guids carrying
+the System specific information.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SYSTEM_NV_DATA_HOB_GUID_H_
+#define _SYSTEM_NV_DATA_HOB_GUID_H_
+
+#define EFI_SYSTEM_NV_DATA_HOB_GUID \
+  {0xd6e5092d, 0xc7b2, 0x4872, {0xaf, 0x66, 0xfd, 0xc0, 0xe6, 0xf9, 0x5e, 0x78}}
+
+typedef struct {
+  EFI_GUID                  SystemNvDataHobGuid;
+  EFI_GUID                  SystemNvDataFvGuid;
+  EFI_LBA                   StartLba;
+  UINTN                     StartLbaOffset;
+  EFI_LBA                   EndLba;
+  UINTN                     EndLbaOffset;
+  UINT32                    DataTypeSignature;
+} NV_SYSTEM_DATA_GUID_TYPE;
+
+extern EFI_GUID gEfiSystemNvDataHobGuid;
+
+#endif

+ 266 - 0
Platform/Intel/QuarkPlatformPkg/Include/Library/PlatformHelperLib.h

@@ -0,0 +1,266 @@
+/** @file
+PlatformHelperLib function prototype definitions.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __PLATFORM_HELPER_LIB_H__
+#define __PLATFORM_HELPER_LIB_H__
+
+#include "Platform.h"
+
+//
+// Function prototypes for routines exported by this library.
+//
+
+/**
+  Find pointer to RAW data in Firmware volume file.
+
+  @param   FvNameGuid       Firmware volume to search. If == NULL search all.
+  @param   FileNameGuid     Firmware volume file to search for.
+  @param   SectionData      Pointer to RAW data section of found file.
+  @param   SectionDataSize  Pointer to UNITN to get size of RAW data.
+
+  @retval  EFI_SUCCESS            Raw Data found.
+  @retval  EFI_INVALID_PARAMETER  FileNameGuid == NULL.
+  @retval  EFI_NOT_FOUND          Firmware volume file not found.
+  @retval  EFI_UNSUPPORTED        Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+  IN CONST EFI_GUID                 *FvNameGuid OPTIONAL,
+  IN CONST EFI_GUID                 *FileNameGuid,
+  OUT VOID                          **SectionData,
+  OUT UINTN                         *SectionDataSize
+  );
+
+/**
+  Find free spi protect register and write to it to protect a flash region.
+
+  @param   DirectValue      Value to directly write to register.
+                            if DirectValue == 0 the use Base & Length below.
+  @param   BaseAddress      Base address of region in Flash Memory Map.
+  @param   Length           Length of region to protect.
+
+  @retval  EFI_SUCCESS      Free spi protect register found & written.
+  @retval  EFI_NOT_FOUND    Free Spi protect register not found.
+  @retval  EFI_DEVICE_ERROR Unable to write to spi protect register.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+  IN CONST UINT32                         DirectValue,
+  IN CONST UINT32                         BaseAddress,
+  IN CONST UINT32                         Length
+  );
+
+/**
+  Lock legacy SPI static configuration information.
+
+  Function will assert if unable to lock config.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockConfig (
+  VOID
+  );
+
+/**
+  Lock regions and config of SPI flash given the policy for this platform.
+
+  Function will assert if unable to lock regions or config.
+
+  @param   PreBootPolicy    If TRUE do Pre Boot Flash Lock Policy.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockPolicy (
+  IN CONST BOOLEAN                        PreBootPolicy
+  );
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+  @retval  TRUE    If system booted with recovery Boot Stage1 image.
+  @retval  FALSE   If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+  VOID
+  );
+
+/**
+  Clear SPI Protect registers.
+
+  @retval EFI_SUCESS         SPI protect registers cleared.
+  @retval EFI_ACCESS_DENIED  Unable to clear SPI protect registers.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformClearSpiProtect (
+  VOID
+  );
+
+/**
+  Determine if an SPI address range is protected.
+
+  @param  SpiBaseAddress  Base of SPI range.
+  @param  Length          Length of SPI range.
+
+  @retval TRUE       Range is protected.
+  @retval FALSE      Range is not protected.
+**/
+BOOLEAN
+EFIAPI
+PlatformIsSpiRangeProtected (
+  IN CONST UINT32                         SpiBaseAddress,
+  IN CONST UINT32                         Length
+  );
+
+/**
+  Set Legacy GPIO Level
+
+  @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
+  @param  GpioNum             GPIO bit to change.
+  @param  HighLevel           If TRUE set GPIO High else Set GPIO low.
+
+**/
+VOID
+EFIAPI
+PlatformLegacyGpioSetLevel (
+  IN CONST UINT32       LevelRegOffset,
+  IN CONST UINT32       GpioNum,
+  IN CONST BOOLEAN      HighLevel
+  );
+
+/**
+  Get Legacy GPIO Level
+
+  @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
+  @param  GpioNum             GPIO bit to check.
+
+  @retval TRUE       If bit is SET.
+  @retval FALSE      If bit is CLEAR.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformLegacyGpioGetLevel (
+  IN CONST UINT32       LevelRegOffset,
+  IN CONST UINT32       GpioNum
+  );
+
+/**
+  Set the direction of Pcal9555 IO Expander GPIO pin.
+
+  @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+  @param  GpioNum            Gpio direction to configure - values 0-7 for Port0
+                             and 8-15 for Port1.
+  @param  CfgAsInput         If TRUE set pin direction as input else set as output.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioSetDir (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST BOOLEAN                        CfgAsInput
+  );
+
+/**
+  Set the level of Pcal9555 IO Expander GPIO high or low.
+
+  @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+  @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+                             for Port1.
+  @param  HighLevel          If TRUE set pin high else set pin low.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioSetLevel (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST BOOLEAN                        HighLevel
+  );
+
+/**
+
+  Enable pull-up/pull-down resistors of Pcal9555 GPIOs.
+
+  @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+  @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+                             for Port1.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioEnablePull (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  );
+
+/**
+
+  Disable pull-up/pull-down resistors of Pcal9555 GPIOs.
+
+  @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+  @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+                             for Port1.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioDisablePull (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  );
+
+BOOLEAN
+EFIAPI
+PlatformPcal9555GpioGetState (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  );
+
+/**
+  Init platform LEDs into known state.
+
+  @param   PlatformType     Executing platform type.
+
+  @retval  EFI_SUCCESS      Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformLedInit (
+  IN CONST EFI_PLATFORM_TYPE              Type
+  );
+
+/**
+  Turn on or off platform flash update LED.
+
+  @param   PlatformType     Executing platform type.
+  @param   TurnOn           If TRUE turn on else turn off.
+
+  @retval  EFI_SUCCESS      Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFlashUpdateLed (
+  IN CONST EFI_PLATFORM_TYPE              Type,
+  IN CONST BOOLEAN                        TurnOn
+  );
+
+#endif // #ifndef __PLATFORM_HELPER_LIB_H__

+ 56 - 0
Platform/Intel/QuarkPlatformPkg/Include/Library/PlatformPcieHelperLib.h

@@ -0,0 +1,56 @@
+/** @file
+PlatformPcieHelperLib function prototype definitions.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __PLATFORM_PCIE_HELPER_LIB_H__
+#define __PLATFORM_PCIE_HELPER_LIB_H__
+
+#include "Platform.h"
+
+//
+// Function prototypes for routines exported by this library.
+//
+
+/**
+  Platform assert PCI express PERST# signal.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTAssert (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  );
+
+/**
+  Platform de assert PCI express PERST# signal.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTDeAssert (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  );
+
+/** Early initialisation of the PCIe controller.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+  @retval   EFI_SUCCESS               Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPciExpressEarlyInit (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  );
+
+#endif // #ifndef __PLATFORM_PCIE_HELPER_LIB_H__

+ 24 - 0
Platform/Intel/QuarkPlatformPkg/Include/Pcal9555.h

@@ -0,0 +1,24 @@
+/** @file
+Definition for Pcal9555 I2c IO Expander.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef __PCAL9555_H__
+#define __PCAL9555_H__
+
+#define PCAL9555_REG_IN_PORT0                        0x00
+#define PCAL9555_REG_IN_PORT1                        0x01
+#define PCAL9555_REG_OUT_PORT0                       0x02
+#define PCAL9555_REG_OUT_PORT1                       0x03
+#define PCAL9555_REG_CFG_PORT0                       0x06
+#define PCAL9555_REG_CFG_PORT1                       0x07
+
+#define PCAL9555_REG_PULL_EN_PORT0                   0x46
+#define PCAL9555_REG_PULL_EN_PORT1                   0x47
+
+#endif

+ 119 - 0
Platform/Intel/QuarkPlatformPkg/Include/Platform.h

@@ -0,0 +1,119 @@
+/** @file
+Quark platform specific information.
+
+Copyright (c) 2013 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#include "Uefi.h"
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+//
+// Constant definition
+//
+#define MAX_SMRAM_RANGES                    4
+#define MAX_NODE                            1
+
+#define QUARK_STAGE1_IMAGE_TYPE_MASK      0xF0
+#define QUARK_STAGE1_BOOT_IMAGE_TYPE      0x00  // Stage1 Boot images 0x00 -> 0x0F.
+#define QUARK_STAGE1_RECOVERY_IMAGE_TYPE  0x10  // Stage1 Recovery images 0x10 -> 0x1F.
+
+#define QUARK_BOOTROM_BASE_ADDRESS        0xFFFE0000  // Base address of Quark ROM in memory map.
+#define QUARK_BOOTROM_SIZE_BYTES          0x20000     // Quark ROM is 128KB.
+#define SMM_DEFAULT_SMBASE                  0x30000     // Default SMBASE address.
+#define SMM_DEFAULT_SMBASE_SIZE_BYTES       0x10000     // Size in bytes of default SMRAM.
+
+//
+// Gpio to be used to assert / deassert PCI express PERST# signal.
+//
+#define PCIEXP_PERST_RESUMEWELL_GPIO        3
+
+//
+// Minimum time in microseconds for assertion of PERST# signal.
+//
+#define PCIEXP_PERST_MIN_ASSERT_US          100
+
+//
+// Microsecond delay post issueing common lane reset.
+//
+#define PCIEXP_DELAY_US_POST_CMNRESET_RESET 1
+
+//
+// Microsecond delay to wait for PLL to lock.
+//
+#define PCIEXP_DELAY_US_WAIT_PLL_LOCK       80
+
+//
+// Microsecond delay post issueing sideband interface reset.
+//
+#define PCIEXP_DELAY_US_POST_SBI_RESET      20
+
+//
+// Microsecond delay post deasserting PERST#.
+//
+#define PCIEXP_DELAY_US_POST_PERST_DEASSERT 10
+
+//
+// Catastrophic Trip point in degrees Celsius for this platform.
+//
+#define PLATFORM_CATASTROPHIC_TRIP_CELSIUS  105
+
+//
+// Platform flash update LED common definitions.
+//
+#define PLATFORM_FLASH_UPDATE_LED_TOGGLE_COUNT   7
+#define PLATFORM_FLASH_UPDATE_LED_TOGGLE_DELTA   (1000 * 1000)  // In Microseconds for EFI_STALL.
+
+//
+// This structure stores the base and size of the ACPI reserved memory used when
+// resuming from S3.  This region must be allocated by the platform code.
+//
+typedef struct {
+  UINT32  AcpiReservedMemoryBase;
+  UINT32  AcpiReservedMemorySize;
+  UINT32  SystemMemoryLength;
+} RESERVED_ACPI_S3_RANGE;
+
+#define RESERVED_ACPI_S3_RANGE_OFFSET (EFI_PAGE_SIZE - sizeof (RESERVED_ACPI_S3_RANGE))
+
+//
+// Define valid platform types.
+// First add value before TypePlatformMax in EFI_PLATFORM_TYPE definition
+// and then add string description to end of EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION.
+// Value shown for supported platforms to help sanity checking with build tools
+// and ACPI method usage.
+//
+typedef enum {
+  TypeUnknown = 0,      // !!! SHOULD BE THE FIRST ENTRY !!!
+  QuarkEmulation = 1,
+  ClantonPeakSVP = 2,
+  KipsBay = 3,
+  CrossHill = 4,
+  ClantonHill = 5,
+  Galileo = 6,
+  TypePlatformRsv7 = 7,
+  GalileoGen2 = 8,
+  TypePlatformMax       // !!! SHOULD BE THE LAST ENTRY !!!
+} EFI_PLATFORM_TYPE;
+
+#define EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION \
+  L"TypeUnknown",\
+  L"QuarkEmulation",\
+  L"ClantonPeakSVP",\
+  L"KipsBay",\
+  L"CrossHill",\
+  L"ClantonHill",\
+  L"Galileo",\
+  L"TypePlatformRsv7",\
+  L"GalileoGen2",\
+
+typedef struct {
+  UINT32  EntryOffset;
+  UINT8   ImageIndex;
+} QUARK_EDKII_STAGE1_HEADER;
+
+#endif

+ 166 - 0
Platform/Intel/QuarkPlatformPkg/Include/PlatformBoards.h

@@ -0,0 +1,166 @@
+/** @file
+Board config definitions for each of the boards supported by this platform
+package.
+
+Copyright (c) 2013 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#include "Platform.h"
+
+#ifndef __PLATFORM_BOARDS_H__
+#define __PLATFORM_BOARDS_H__
+
+//
+// Constant definition
+//
+
+//
+// Default resume well TPM reset.
+//
+#define PLATFORM_RESUMEWELL_TPM_RST_GPIO                5
+
+//
+// Basic Configs for GPIO table definitions.
+//
+#define NULL_LEGACY_GPIO_INITIALIZER                    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+#define ALL_INPUT_LEGACY_GPIO_INITIALIZER               {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define QUARK_EMULATION_LEGACY_GPIO_INITIALIZER         ALL_INPUT_LEGACY_GPIO_INITIALIZER
+#define CLANTON_PEAK_SVP_LEGACY_GPIO_INITIALIZER        {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x3f,0x00,0x00,0x3f,0x3f,0x00,0x3f,0x00}
+#define KIPS_BAY_LEGACY_GPIO_INITIALIZER                {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x25,0x10,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define CROSS_HILL_LEGACY_GPIO_INITIALIZER              {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x03,0x10,0x00,0x03,0x03,0x00,0x3f,0x00}
+#define CLANTON_HILL_LEGACY_GPIO_INITIALIZER            {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x06,0x10,0x00,0x04,0x04,0x00,0x3f,0x00}
+#define GALILEO_LEGACY_GPIO_INITIALIZER                 {0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x21,0x14,0x00,0x00,0x00,0x00,0x3f,0x00}
+#define GALILEO_GEN2_LEGACY_GPIO_INITIALIZER            {0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x3f,0x1c,0x02,0x00,0x00,0x00,0x00,0x3f,0x00}
+
+#define NULL_GPIO_CONTROLLER_INITIALIZER                {0,0,0,0,0,0,0,0}
+#define ALL_INPUT_GPIO_CONTROLLER_INITIALIZER           NULL_GPIO_CONTROLLER_INITIALIZER
+#define QUARK_EMULATION_GPIO_CONTROLLER_INITIALIZER     NULL_GPIO_CONTROLLER_INITIALIZER
+#define CLANTON_PEAK_SVP_GPIO_CONTROLLER_INITIALIZER    NULL_GPIO_CONTROLLER_INITIALIZER
+#define KIPS_BAY_GPIO_CONTROLLER_INITIALIZER            {0x05,0x05,0,0,0,0,0,0}
+#define CROSS_HILL_GPIO_CONTROLLER_INITIALIZER          {0x0D,0x2D,0,0,0,0,0,0}
+#define CLANTON_HILL_GPIO_CONTROLLER_INITIALIZER        {0x01,0x39,0,0,0,0,0,0}
+#define GALILEO_GPIO_CONTROLLER_INITIALIZER             {0x05,0x15,0,0,0,0,0,0}
+#define GALILEO_GEN2_GPIO_CONTROLLER_INITIALIZER        {0x05,0x05,0,0,0,0,0,0}
+
+//
+// Legacy Gpio to be used to assert / deassert PCI express PERST# signal
+// on Galileo Gen 2 platform.
+//
+#define GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO       0
+
+//
+// Io expander slave address.
+//
+
+//
+// On Galileo value of Jumper J2 determines slave address of io expander.
+//
+#define GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO     5
+#define GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR              0x20
+#define GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR              0x21
+
+//
+// Three IO Expmanders at fixed addresses on Galileo Gen2.
+//
+#define GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR             0x25
+#define GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR             0x26
+#define GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR             0x27
+
+//
+// Led GPIOs for flash update / recovery.
+//
+#define GALILEO_FLASH_UPDATE_LED_RESUMEWELL_GPIO        1
+#define GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO   5
+
+//
+// Legacy GPIO config struct for each element in PLATFORM_LEGACY_GPIO_TABLE_DEFINITION.
+//
+typedef struct {
+  UINT32  CoreWellEnable;               ///< Value for QNC NC Reg R_QNC_GPIO_CGEN_CORE_WELL.
+  UINT32  CoreWellIoSelect;             ///< Value for QNC NC Reg R_QNC_GPIO_CGIO_CORE_WELL.
+  UINT32  CoreWellLvlForInputOrOutput;  ///< Value for QNC NC Reg R_QNC_GPIO_CGLVL_CORE_WELL.
+  UINT32  CoreWellTriggerPositiveEdge;  ///< Value for QNC NC Reg R_QNC_GPIO_CGTPE_CORE_WELL.
+  UINT32  CoreWellTriggerNegativeEdge;  ///< Value for QNC NC Reg R_QNC_GPIO_CGTNE_CORE_WELL.
+  UINT32  CoreWellGPEEnable;            ///< Value for QNC NC Reg R_QNC_GPIO_CGGPE_CORE_WELL.
+  UINT32  CoreWellSMIEnable;            ///< Value for QNC NC Reg R_QNC_GPIO_CGSMI_CORE_WELL.
+  UINT32  CoreWellTriggerStatus;        ///< Value for QNC NC Reg R_QNC_GPIO_CGTS_CORE_WELL.
+  UINT32  CoreWellNMIEnable;            ///< Value for QNC NC Reg R_QNC_GPIO_CGNMIEN_CORE_WELL.
+  UINT32  ResumeWellEnable;             ///< Value for QNC NC Reg R_QNC_GPIO_RGEN_RESUME_WELL.
+  UINT32  ResumeWellIoSelect;           ///< Value for QNC NC Reg R_QNC_GPIO_RGIO_RESUME_WELL.
+  UINT32  ResumeWellLvlForInputOrOutput;///< Value for QNC NC Reg R_QNC_GPIO_RGLVL_RESUME_WELL.
+  UINT32  ResumeWellTriggerPositiveEdge;///< Value for QNC NC Reg R_QNC_GPIO_RGTPE_RESUME_WELL.
+  UINT32  ResumeWellTriggerNegativeEdge;///< Value for QNC NC Reg R_QNC_GPIO_RGTNE_RESUME_WELL.
+  UINT32  ResumeWellGPEEnable;          ///< Value for QNC NC Reg R_QNC_GPIO_RGGPE_RESUME_WELL.
+  UINT32  ResumeWellSMIEnable;          ///< Value for QNC NC Reg R_QNC_GPIO_RGSMI_RESUME_WELL.
+  UINT32  ResumeWellTriggerStatus;      ///< Value for QNC NC Reg R_QNC_GPIO_RGTS_RESUME_WELL.
+  UINT32  ResumeWellNMIEnable;          ///< Value for QNC NC Reg R_QNC_GPIO_RGNMIEN_RESUME_WELL.
+} BOARD_LEGACY_GPIO_CONFIG;
+
+//
+// GPIO controller config struct for each element in PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION.
+//
+typedef struct {
+  UINT32  PortADR;                      ///< Value for IOH REG GPIO_SWPORTA_DR.
+  UINT32  PortADir;                     ///< Value for IOH REG GPIO_SWPORTA_DDR.
+  UINT32  IntEn;                        ///< Value for IOH REG GPIO_INTEN.
+  UINT32  IntMask;                      ///< Value for IOH REG GPIO_INTMASK.
+  UINT32  IntType;                      ///< Value for IOH REG GPIO_INTTYPE_LEVEL.
+  UINT32  IntPolarity;                  ///< Value for IOH REG GPIO_INT_POLARITY.
+  UINT32  Debounce;                     ///< Value for IOH REG GPIO_DEBOUNCE.
+  UINT32  LsSync;                       ///< Value for IOH REG GPIO_LS_SYNC.
+} BOARD_GPIO_CONTROLLER_CONFIG;
+
+///
+/// Table of BOARD_LEGACY_GPIO_CONFIG structures for each board supported
+/// by this platform package.
+/// Table indexed with EFI_PLATFORM_TYPE enum value.
+///
+#define PLATFORM_LEGACY_GPIO_TABLE_DEFINITION \
+  /* EFI_PLATFORM_TYPE - TypeUnknown*/\
+  NULL_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - QuarkEmulation*/\
+  QUARK_EMULATION_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - ClantonPeakSVP*/\
+  CLANTON_PEAK_SVP_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - KipsBay*/\
+  KIPS_BAY_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - CrossHill*/\
+  CROSS_HILL_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - ClantonHill*/\
+  CLANTON_HILL_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - Galileo*/\
+  GALILEO_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - TypePlatformRsv7*/\
+  NULL_LEGACY_GPIO_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - GalileoGen2*/\
+  GALILEO_GEN2_LEGACY_GPIO_INITIALIZER,\
+
+///
+/// Table of BOARD_GPIO_CONTROLLER_CONFIG structures for each board
+/// supported by this platform package.
+/// Table indexed with EFI_PLATFORM_TYPE enum value.
+///
+#define PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION \
+  /* EFI_PLATFORM_TYPE - TypeUnknown*/\
+  NULL_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - QuarkEmulation*/\
+  QUARK_EMULATION_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - ClantonPeakSVP*/\
+  CLANTON_PEAK_SVP_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - KipsBay*/\
+  KIPS_BAY_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - CrossHill*/\
+  CROSS_HILL_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - ClantonHill*/\
+  CLANTON_HILL_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - Galileo*/\
+  GALILEO_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - TypePlatformRsv7 */\
+  NULL_GPIO_CONTROLLER_INITIALIZER,\
+  /* EFI_PLATFORM_TYPE - GalileoGen2*/\
+  GALILEO_GEN2_GPIO_CONTROLLER_INITIALIZER,\
+
+#endif

+ 82 - 0
Platform/Intel/QuarkPlatformPkg/Include/Protocol/GlobalNvsArea.h

@@ -0,0 +1,82 @@
+/** @file
+Definition of the global NVS area protocol.  This protocol
+publishes the address and format of a global ACPI NVS buffer
+used as a communications buffer between SMM code and ASL code.
+The format is derived from the ACPI reference code, version 0.95.
+Note:  Data structures defined in this protocol are not naturally aligned.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GLOBAL_NVS_AREA_H_
+#define _GLOBAL_NVS_AREA_H_
+
+//
+// Forward reference for pure ANSI compatability
+//
+
+typedef struct _EFI_GLOBAL_NVS_AREA_PROTOCOL EFI_GLOBAL_NVS_AREA_PROTOCOL;
+
+//
+// Global NVS Area Protocol GUID
+//
+#define EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID \
+{ 0x74e1e48, 0x8132, 0x47a1, {0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc} }
+
+
+//
+// Global NVS Area definition
+//
+#pragma pack (1)
+typedef struct {
+  //
+  // Miscellaneous Dynamic Values
+  //
+  UINT32      OperatingSystemType;    // Os type indicator
+  UINT32      Cfgd;                   // System configuration description
+  UINT32      HpetEnable;
+
+  UINT32      Pm1blkIoBaseAddress;
+  UINT32      PmbaIoBaseAddress;
+  UINT32      Gpe0blkIoBaseAddress;
+  UINT32      GbaIoBaseAddress;
+
+  UINT32      SmbaIoBaseAddress;
+  UINT32      Reserved1;
+  UINT32      WdtbaIoBaseAddress;
+
+  UINT32      HpetBaseAddress;
+  UINT32      HpetSize;
+  UINT32      PciExpressBaseAddress;
+  UINT32      PciExpressSize;
+
+  UINT32      RcbaMmioBaseAddress;
+  UINT32      RcbaMmioSize;
+  UINT32      IoApicBaseAddress;
+  UINT32      IoApicSize;
+
+  UINT32      TpmPresent;
+  UINT32      DBG2Present;
+  UINT32      PlatformType;           // Set to one of EFI_PLATFORM_TYPE enums.
+  UINT32      AlternateSla;           // If TRUE use alternate I2C Slave addresses.
+
+  UINT8       Reserved[512 - 4 * 22]; // Total 512 Bytes
+} EFI_GLOBAL_NVS_AREA;
+#pragma pack ()
+
+//
+// Global NVS Area Protocol
+//
+struct _EFI_GLOBAL_NVS_AREA_PROTOCOL {
+  EFI_GLOBAL_NVS_AREA     *Area;
+};
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gEfiGlobalNvsAreaProtocolGuid;
+
+#endif

+ 23 - 0
Platform/Intel/QuarkPlatformPkg/Include/Protocol/PlatformSmmSpiReady.h

@@ -0,0 +1,23 @@
+/** @file
+This protocol indicates that the platform SPI interface is ready for use.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#ifndef _PLATFORM_SPI_READY_H_
+#define _PLATFORM_SPI_READY_H_
+
+// {7A5DBC75-5B2B-4e67-BDE1-D48EEE761562}
+#define EFI_SMM_SPI_READY_PROTOCOL_GUID  \
+  { 0x7a5dbc75, 0x5b2b, 0x4e67, 0xbd, 0xe1, 0xd4, 0x8e, 0xee, 0x76, 0x15, 0x62 }
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                     gEfiSmmSpiReadyProtocolGuid;
+
+#endif

+ 472 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.c

@@ -0,0 +1,472 @@
+/** @file
+This file include all platform action which can be customized
+by IBV/OEM.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PlatformBootManager.h"
+
+/**
+  Return the index of the load option in the load option array.
+
+  The function consider two load options are equal when the
+  OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+  @param Key    Pointer to the load option to be found.
+  @param Array  Pointer to the array of load options to be found.
+  @param Count  Number of entries in the Array.
+
+  @retval -1          Key wasn't found in the Array.
+  @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+PlatformFindLoadOption (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+  IN UINTN                              Count
+  )
+{
+  UINTN                             Index;
+
+  for (Index = 0; Index < Count; Index++) {
+    if ((Key->OptionType == Array[Index].OptionType) &&
+        (Key->Attributes == Array[Index].Attributes) &&
+        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
+      return (INTN) Index;
+    }
+  }
+
+  return -1;
+}
+
+VOID
+PlatformRegisterFvBootOption (
+  EFI_GUID  *FileGuid,
+  CHAR16    *Description,
+  UINT32    Attributes
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_HANDLE                        *HandleBuffer;
+  UINTN                             HandleCount;
+  UINTN                             IndexFv;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL     *Fv;
+  CHAR16                            *UiSection;
+  UINTN                             UiSectionLength;
+  UINT32                            AuthenticationStatus;
+  EFI_HANDLE                        FvHandle;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
+  UINTN                             BootOptionCount;
+  UINTN                             OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
+
+  //
+  // Locate all available FVs.
+  //
+  HandleBuffer = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareVolume2ProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Go through FVs one by one to find the required FFS file
+  //
+  for (IndexFv = 0, FvHandle = NULL; IndexFv < HandleCount && FvHandle == NULL; IndexFv++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[IndexFv],
+                    &gEfiFirmwareVolume2ProtocolGuid,
+                    (VOID **)&Fv
+                    );
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    //
+    // Attempt to read a EFI_SECTION_USER_INTERFACE section from the required FFS file
+    //
+    UiSection = NULL;
+    Status = Fv->ReadSection (
+                   Fv,
+                   FileGuid,
+                   EFI_SECTION_USER_INTERFACE,
+                   0,
+                   (VOID **) &UiSection,
+                   &UiSectionLength,
+                   &AuthenticationStatus
+                   );
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    FreePool (UiSection);
+
+    //
+    // Save the handle of the FV where the FFS file was found
+    //
+    FvHandle = HandleBuffer[IndexFv];
+  }
+
+  //
+  // Free the buffer of FV handles
+  //
+  FreePool (HandleBuffer);
+
+  //
+  // If the FFS file was not found, then return
+  //
+  if (FvHandle == NULL) {
+    return;
+  }
+
+  //
+  // Create a device path for the FFS file that was found
+  //
+  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+  DevicePath = AppendDevicePathNode (
+                 DevicePathFromHandle (FvHandle),
+                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+                 );
+
+  //
+  // Create and add a new load option for the FFS file that was found
+  //
+  Status = EfiBootManagerInitializeLoadOption (
+             &NewOption,
+             LoadOptionNumberUnassigned,
+             LoadOptionTypeBoot,
+             Attributes,
+             Description,
+             DevicePath,
+             NULL,
+             0
+             );
+  if (!EFI_ERROR (Status)) {
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
+
+    if (OptionIndex == -1) {
+      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);
+      ASSERT_EFI_ERROR (Status);
+    }
+    EfiBootManagerFreeLoadOption (&NewOption);
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+  }
+}
+
+VOID
+EFIAPI
+InternalBdsEmptyCallbackFuntion (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  return;
+}
+
+/**
+  Do the platform specific action before the console is connected.
+
+  Such as:
+    Update console variable;
+    Register new Driver#### or Boot####;
+    Signal ReadyToLock event.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         Index;
+  EFI_INPUT_KEY                 Enter;
+  EFI_INPUT_KEY                 F2;
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
+  ESRT_MANAGEMENT_PROTOCOL      *EsrtManagement;
+  EFI_BOOT_MODE                 BootMode;
+  EFI_ACPI_S3_SAVE_PROTOCOL     *AcpiS3Save;
+  EFI_HANDLE                    Handle;
+  EFI_EVENT                     EndOfDxeEvent;
+
+  //
+  // Update the console variables.
+  //
+  for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) {
+    if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+      EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL);
+    }
+
+    if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+      EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL);
+    }
+
+    if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+      EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL);
+    }
+  }
+
+  //
+  // Register ENTER as CONTINUE key
+  //
+  Enter.ScanCode    = SCAN_NULL;
+  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+  EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+
+  //
+  // Map F2 to Boot Manager Menu
+  //
+  F2.ScanCode    = SCAN_F2;
+  F2.UnicodeChar = CHAR_NULL;
+  EfiBootManagerGetBootManagerMenu (&BootOption);
+  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);
+
+  //
+  // Register UEFI Shell
+  //
+  PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE);
+
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
+  BootMode = GetBootModeHob();
+  switch (BootMode) {
+  case BOOT_ON_FLASH_UPDATE:
+    DEBUG((DEBUG_INFO, "ProcessCapsules Before EndOfDxe ......\n"));
+    Status = ProcessCapsules ();
+    DEBUG((DEBUG_INFO, "ProcessCapsules %r\n", Status));
+    break;
+  case BOOT_IN_RECOVERY_MODE:
+    break;
+  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+  case BOOT_WITH_MINIMAL_CONFIGURATION:
+  case BOOT_ON_S4_RESUME:
+    if (EsrtManagement != NULL) {
+      //
+      // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
+      //
+      EsrtManagement->LockEsrtRepository();
+    }
+    break;
+  default:
+    //
+    // Require to sync ESRT from FMP in a new boot
+    //
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
+    break;
+  }
+
+  //
+  // Prepare for S3
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **)&AcpiS3Save);
+  if (!EFI_ERROR (Status)) {
+    AcpiS3Save->S3Save (AcpiS3Save, NULL);
+  }
+
+  //
+  // Inform PI SMM drivers that BDS may run 3rd party code
+  // Create and signal End of DXE event group
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  InternalBdsEmptyCallbackFuntion,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+  gBS->SignalEvent (EndOfDxeEvent);
+  gBS->CloseEvent (EndOfDxeEvent);
+
+  DEBUG((EFI_D_INFO,"All EndOfDxe callbacks have returned successfully\n"));
+
+  //
+  // Install SMM Ready To Lock protocol so all resources can be locked down
+  // before BDS runs 3rd party code.  This action must be done last so all
+  // other SMM driver signals are processed before this final lock down action.
+  //
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &Handle,
+                  &gEfiDxeSmmReadyToLockProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+}
+
+/**
+  Do the platform specific action after the console is connected.
+
+  Such as:
+    Dynamically switch output mode;
+    Signal console ready platform customized event;
+    Run diagnostics like memory testing;
+    Connect certain devices;
+    Dispatch additional option ROMs
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+  VOID
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_BOOT_MODE                  BootMode;
+  ESRT_MANAGEMENT_PROTOCOL       *EsrtManagement;
+  VOID                           *Buffer;
+  UINTN                          Size;
+
+  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
+  if (EFI_ERROR(Status)) {
+    EsrtManagement = NULL;
+  }
+
+  BootMode = GetBootModeHob();
+
+  DEBUG((DEBUG_INFO, "PlatformBootManagerAfterConsole(): BootMode = %02x\n", BootMode));
+
+  switch (BootMode) {
+  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+  case BOOT_WITH_MINIMAL_CONFIGURATION:
+  case BOOT_ON_S4_RESUME:
+    EfiBootManagerRefreshAllBootOption ();
+    break;
+
+  case BOOT_ON_FLASH_UPDATE:
+    if (FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
+      EfiBootManagerConnectAll ();
+      EfiBootManagerRefreshAllBootOption ();
+
+      //
+      // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
+      //
+      if (EsrtManagement != NULL) {
+        EsrtManagement->SyncEsrtFmp();
+      }
+
+      DEBUG((DEBUG_INFO, "ProcessCapsules After ConnectAll ......\n"));
+      Status = ProcessCapsules();
+      DEBUG((DEBUG_INFO, "ProcessCapsules %r\n", Status));
+    }
+    break;
+
+  default:
+    EfiBootManagerConnectAll ();
+    EfiBootManagerRefreshAllBootOption ();
+
+    //
+    // Sync ESRT Cache from FMP Instance on demand after Connect All
+    //
+    if (EsrtManagement != NULL) {
+      EsrtManagement->SyncEsrtFmp();
+    }
+    break;
+  }
+
+  Print (
+    L"\n"
+    L"F2      to enter Boot Manager Menu.\n"
+    L"ENTER   to boot directly.\n"
+    L"\n"
+    );
+
+  //
+  // Check if the platform is using test key.
+  //
+  Status = GetSectionFromAnyFv(
+             PcdGetPtr(PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid),
+             EFI_SECTION_RAW,
+             0,
+             &Buffer,
+             &Size
+             );
+  if (!EFI_ERROR(Status)) {
+    if ((Size == PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer)) &&
+        (CompareMem(Buffer, PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer), Size) == 0)) {
+      Print(L"WARNING: Recovery Test Key is used.\n");
+      PcdSetBoolS(PcdTestKeyUsed, TRUE);
+    }
+    FreePool(Buffer);
+  }
+  Status = GetSectionFromAnyFv(
+             PcdGetPtr(PcdEdkiiPkcs7TestPublicKeyFileGuid),
+             EFI_SECTION_RAW,
+             0,
+             &Buffer,
+             &Size
+             );
+  if (!EFI_ERROR(Status)) {
+    if ((Size == PcdGetSize(PcdPkcs7CertBuffer)) &&
+        (CompareMem(Buffer, PcdGetPtr(PcdPkcs7CertBuffer), Size) == 0)) {
+      Print(L"WARNING: Capsule Test Key is used.\n");
+      PcdSetBoolS(PcdTestKeyUsed, TRUE);
+    }
+    FreePool(Buffer);
+  }
+
+  //
+  // Use a DynamicHii type pcd to save the boot status, which is used to
+  // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
+  //
+  if (PcdGetBool(PcdBootState)) {
+    Status = PcdSetBoolS (PcdBootState, FALSE);
+    ASSERT_EFI_ERROR (Status);
+  }
+}
+
+/**
+  This function is called each second during the boot manager waits the timeout.
+
+  @param TimeoutRemain  The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+  UINT16  TimeoutRemain
+  )
+{
+  Print (L"\r%-2d seconds remained...", TimeoutRemain);
+}
+
+/**
+  The function is called when no boot option could be launched,
+  including platform recovery options and options pointing to applications
+  built into firmware volumes.
+
+  If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+  VOID
+  )
+{
+  return;
+}
+

+ 49 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManager.h

@@ -0,0 +1,49 @@
+/** @file
+Head file for BDS Platform specific code
+
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_BOOT_MANAGER_H
+#define _PLATFORM_BOOT_MANAGER_H
+
+#include <PiDxe.h>
+
+#include <Library/PlatformBootManagerLib.h>
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/AcpiS3Save.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/EsrtManagement.h>
+#include <Guid/DebugAgentGuid.h>
+#include <Guid/EventGroup.h>
+#include <Guid/PcAnsi.h>
+#include <Guid/TtyTerm.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HobLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DxeServicesLib.h>
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN  BIT1
+#define STD_ERROR   BIT2
+
+#endif // _PLATFORM_BOOT_MANAGER_H

+ 83 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf

@@ -0,0 +1,83 @@
+## @file
+#  Include all platform action which can be customized by IBV/OEM.
+#
+#  Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformBootManagerLib
+  FILE_GUID                      = EC67889B-9E62-4c81-8CA0-86E6A6EEE61A
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
+  CONSTRUCTOR                    = InitializePlatformBootManagerLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PlatformData.c
+  PlatformBootManager.c
+  PlatformBootManager.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  IntelFrameworkPkg/IntelFrameworkPkg.dec
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+  SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ShellPkg/ShellPkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  PcdLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+  UefiBootManagerLib
+  PrintLib
+  HobLib
+  CapsuleLib
+  DxeServicesLib
+
+[Protocols]
+  gEfiFirmwareVolume2ProtocolGuid
+  gEfiAcpiS3SaveProtocolGuid
+  gEfiDxeSmmReadyToLockProtocolGuid
+  gEsrtManagementProtocolGuid
+
+[Guids]
+  gEfiPcAnsiGuid
+  gEfiVT100Guid
+  gEfiVT100PlusGuid
+  gEfiVTUTF8Guid
+  gEfiTtyTermGuid
+  gEfiEndOfDxeEventGroupGuid
+  gUefiShellFileGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+  gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiPkcs7TestPublicKeyFileGuid
+  gEfiSecurityPkgTokenSpaceGuid.PcdRsa2048Sha256PublicKeyBuffer
+  gEfiSecurityPkgTokenSpaceGuid.PcdPkcs7CertBuffer
+  gEfiMdeModulePkgTokenSpaceGuid.PcdTestKeyUsed
+

+ 275 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformBootManagerLib/PlatformData.c

@@ -0,0 +1,275 @@
+/** @file
+Defined the platform specific device path which will be filled to
+ConIn/ConOut variables.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PlatformBootManager.h"
+
+///
+/// the short form device path for Usb keyboard
+///
+#define CLASS_HID           3
+#define SUBCLASS_BOOT       1
+#define PROTOCOL_KEYBOARD   1
+
+///
+/// PcdDefaultTerminalType values
+///
+#define PCANSITYPE                0
+#define VT100TYPE                 1
+#define VT100PLUSTYPE             2
+#define VTUTF8TYPE                3
+#define TTYTERMTYPE               4
+
+//
+// Below is the platform console device path
+//
+typedef struct {
+  ACPI_HID_DEVICE_PATH            PciRootBridge;
+  PCI_DEVICE_PATH                 PciUart;
+  UART_DEVICE_PATH                Uart;
+  VENDOR_DEVICE_PATH              TerminalType;
+  EFI_DEVICE_PATH_PROTOCOL        End;
+} PCI_UART_DEVICE_PATH;
+
+typedef struct {
+  VENDOR_DEVICE_PATH        VendorHardware;
+  UART_DEVICE_PATH          Uart;
+  VENDOR_DEVICE_PATH        TerminalType;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} VENDOR_UART_DEVICE_PATH;
+
+typedef struct {
+  USB_CLASS_DEVICE_PATH           UsbClass;
+  EFI_DEVICE_PATH_PROTOCOL        End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+  { \
+    { \
+      HARDWARE_DEVICE_PATH, \
+      HW_PCI_DP, \
+      { \
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    (Func), \
+    (Dev) \
+  }
+
+#define gEndEntire \
+  { \
+    END_DEVICE_PATH_TYPE, \
+    END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+    { \
+      END_DEVICE_PATH_LENGTH, \
+      0 \
+    } \
+  }
+
+//
+// Platform specific serial device path
+//
+PCI_UART_DEVICE_PATH   gPciUartDevicePath0 = {
+  PNPID_DEVICE_PATH_NODE(0x0A03),
+  PCI_DEVICE_PATH_NODE(1, 20),
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_UART_DP,
+      {
+        (UINT8)(sizeof (UART_DEVICE_PATH)),
+        (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)
+      }
+    },
+    0,         // Reserved
+    921600,    // BaudRate
+    8,         // DataBits
+    1,         // Parity
+    1          // StopBits
+  },
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_VENDOR_DP,
+      {
+        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      },
+    },
+    DEVICE_PATH_MESSAGING_PC_ANSI
+  },
+  gEndEntire
+};
+
+PCI_UART_DEVICE_PATH   gPciUartDevicePath1 = {
+  PNPID_DEVICE_PATH_NODE(0x0A03),
+  PCI_DEVICE_PATH_NODE(5, 20),
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_UART_DP,
+      {
+        (UINT8)(sizeof (UART_DEVICE_PATH)),
+        (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)
+      }
+    },
+    0,         // Reserved
+    921600,    // BaudRate
+    8,         // DataBits
+    1,         // Parity
+    1          // StopBits
+  },
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_VENDOR_DP,
+      {
+        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    DEVICE_PATH_MESSAGING_PC_ANSI
+  },
+  gEndEntire
+};
+
+VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    EFI_DEBUG_AGENT_GUID,
+  },
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_UART_DP,
+      {
+        (UINT8) (sizeof (UART_DEVICE_PATH)),
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+      }
+    },
+    0,  // Reserved
+    0,  // BaudRate - Default
+    0,  // DataBits - Default
+    0,  // Parity   - Default
+    0,  // StopBits - Default
+  },
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_VENDOR_DP,
+      {
+        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    DEVICE_PATH_MESSAGING_PC_ANSI
+  },
+  gEndEntire
+};
+
+USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_USB_CLASS_DP,
+      {
+        (UINT8)(sizeof (USB_CLASS_DEVICE_PATH)),
+        (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+      }
+    },
+    0xffff,              // VendorId  - Match any vendor
+    0xffff,              // ProductId - Match any product
+    CLASS_HID,           // DeviceClass
+    SUBCLASS_BOOT,       // DeviceSubClass
+    PROTOCOL_KEYBOARD    // DeviceProtocol
+  },
+  gEndEntire
+};
+
+//
+// Predefined platform default console device path
+//
+PLATFORM_CONSOLE_CONNECT_ENTRY   gPlatformConsole[] = {
+  { (EFI_DEVICE_PATH_PROTOCOL *) &gPciUartDevicePath0,         (CONSOLE_OUT | CONSOLE_IN) },
+  { (EFI_DEVICE_PATH_PROTOCOL *) &gPciUartDevicePath1,         (CONSOLE_OUT | CONSOLE_IN) },
+  { (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,   (CONSOLE_OUT | CONSOLE_IN) },
+  { (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, (CONSOLE_IN)               },
+  { NULL, 0 }
+};
+
+EFI_STATUS
+EFIAPI
+InitializePlatformBootManagerLib (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_GUID  *TerminalTypeGuid;
+
+  //
+  // Update UART device path nodes based on UART PCD settings
+  //
+  gPciUartDevicePath0.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
+  gPciUartDevicePath0.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
+  gPciUartDevicePath0.Uart.Parity   = PcdGet8 (PcdUartDefaultParity);
+  gPciUartDevicePath0.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
+  gPciUartDevicePath1.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
+  gPciUartDevicePath1.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
+  gPciUartDevicePath1.Uart.Parity   = PcdGet8 (PcdUartDefaultParity);
+  gPciUartDevicePath1.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
+
+  //
+  // Update Vendor device path nodes based on terminal type PCD settings
+  //
+  switch (PcdGet8 (PcdDefaultTerminalType)) {
+  case PCANSITYPE:
+    TerminalTypeGuid = &gEfiPcAnsiGuid;
+    break;
+  case VT100TYPE:
+    TerminalTypeGuid = &gEfiVT100Guid;
+    break;
+  case VT100PLUSTYPE:
+    TerminalTypeGuid = &gEfiVT100PlusGuid;
+    break;
+  case VTUTF8TYPE:
+    TerminalTypeGuid = &gEfiVTUTF8Guid;
+    break;
+  case TTYTERMTYPE:
+    TerminalTypeGuid = &gEfiTtyTermGuid;
+    break;
+  default:
+    TerminalTypeGuid = &gEfiPcAnsiGuid;
+    break;
+  }
+  CopyGuid (&gPciUartDevicePath0.TerminalType.Guid, TerminalTypeGuid);
+  CopyGuid (&gPciUartDevicePath1.TerminalType.Guid, TerminalTypeGuid);
+
+  return EFI_SUCCESS;
+}

+ 51 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/CommonHeader.h

@@ -0,0 +1,51 @@
+/** @file
+Common header file shared by all source files in this component.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Platform.h>
+#include <PlatformBoards.h>
+#include <Pcal9555.h>
+#include <QNCAccess.h>
+#include <Library/QNCAccessLib.h>
+#include <IohAccess.h>
+
+#include <Library/PlatformHelperLib.h>
+
+//
+// Routines shared between souce modules in this component.
+//
+
+EFI_STATUS
+WriteFirstFreeSpiProtect (
+  IN CONST UINT32                         PchRootComplexBar,
+  IN CONST UINT32                         DirectValue,
+  IN CONST UINT32                         BaseAddress,
+  IN CONST UINT32                         Length,
+  OUT UINT32                              *OffsetPtr
+  );
+
+VOID
+Pcal9555SetPortRegBit (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST UINT8                          RegBase,
+  IN CONST BOOLEAN                        LogicOne
+  );
+
+#endif

+ 70 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/DxePlatformHelperLib.inf

@@ -0,0 +1,70 @@
+## @file
+# Library producing helper routines for this platform.
+#
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxePlatformHelperLib
+  FILE_GUID                      = 02805010-2591-4ed3-827B-A218F34AE0D7
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformHelperLib|DXE_DRIVER DXE_RUNTIME_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformHelperLib.c
+  PlatformHelperDxe.c
+  PlatformLeds.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  BaseMemoryLib
+  SerialPortLib
+  S3BootScriptLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  DxeServicesLib
+  HobLib
+  IntelQNCLib
+  I2cLib
+
+[Protocols]
+  gEfiSpiProtocolGuid
+  gEfiSmmSpiProtocolGuid
+  gEfiSmmBase2ProtocolGuid
+  gEdkiiVariableLockProtocolGuid                ## CONSUMES
+
+[Guids]
+  gEfiGlobalVariableGuid
+  gEfiImageSecurityDatabaseGuid
+  gEfiQuarkCapsuleGuid
+  gQuarkVariableLockGuid                        ## CONSUMES
+  gEfiMemoryConfigDataGuid                      ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
+  gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase
+  gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoverySize
+  gQuarkPlatformTokenSpaceGuid.PcdPkX509File
+  gQuarkPlatformTokenSpaceGuid.PcdKekX509File
+  gQuarkPlatformTokenSpaceGuid.PcdKekRsa2048File
+  gQuarkPlatformTokenSpaceGuid.PcdSpiFlashDeviceSize

+ 45 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PeiPlatformHelperLib.inf

@@ -0,0 +1,45 @@
+## @file
+# Library producing helper routines for this platform.
+#
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiPlatformHelperLib
+  FILE_GUID                      = 024D3127-7B60-48f4-A6FE-726E19CD4CEB
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformHelperLib|PEIM PEI_CORE SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformHelperLib.c
+  PlatformHelperPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  BaseMemoryLib
+  PeiServicesTablePointerLib
+  PeiServicesLib
+  SerialPortLib
+  QNCAccessLib
+  I2cLib
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base

+ 337 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c

@@ -0,0 +1,337 @@
+/** @file
+Implementation of helper routines for DXE environment.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/Spi.h>
+#include <Protocol/VariableLock.h>
+
+#include <Guid/MemoryConfigData.h>
+#include <Guid/QuarkVariableLock.h>
+
+#include "CommonHeader.h"
+
+#define FLASH_BLOCK_SIZE            SIZE_4KB
+
+//
+// Global variables.
+//
+EFI_SPI_PROTOCOL                    *mPlatHelpSpiProtocolRef = NULL;
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this component.
+//
+
+//
+// Routines shared with other souce modules in this component.
+//
+
+EFI_SPI_PROTOCOL *
+LocateSpiProtocol (
+  IN  EFI_SMM_SYSTEM_TABLE2             *Smst
+  )
+{
+  if (mPlatHelpSpiProtocolRef == NULL) {
+    if (Smst != NULL) {
+      Smst->SmmLocateProtocol (
+              &gEfiSmmSpiProtocolGuid,
+              NULL,
+              (VOID **) &mPlatHelpSpiProtocolRef
+              );
+    } else {
+      gBS->LocateProtocol (
+             &gEfiSpiProtocolGuid,
+             NULL,
+             (VOID **) &mPlatHelpSpiProtocolRef
+             );
+    }
+    ASSERT (mPlatHelpSpiProtocolRef != NULL);
+  }
+  return mPlatHelpSpiProtocolRef;
+}
+
+//
+// Routines exported by this source module.
+//
+
+/**
+  Find pointer to RAW data in Firmware volume file.
+
+  @param   FvNameGuid       Firmware volume to search. If == NULL search all.
+  @param   FileNameGuid     Firmware volume file to search for.
+  @param   SectionData      Pointer to RAW data section of found file.
+  @param   SectionDataSize  Pointer to UNITN to get size of RAW data.
+
+  @retval  EFI_SUCCESS            Raw Data found.
+  @retval  EFI_INVALID_PARAMETER  FileNameGuid == NULL.
+  @retval  EFI_NOT_FOUND          Firmware volume file not found.
+  @retval  EFI_UNSUPPORTED        Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+  IN CONST EFI_GUID                 *FvNameGuid OPTIONAL,
+  IN CONST EFI_GUID                 *FileNameGuid,
+  OUT VOID                          **SectionData,
+  OUT UINTN                         *SectionDataSize
+  )
+{
+  if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (FvNameGuid != NULL) {
+    return EFI_UNSUPPORTED;  // Searching in specific FV unsupported in DXE.
+  }
+
+  return GetSectionFromAnyFv (FileNameGuid, EFI_SECTION_RAW, 0, SectionData, SectionDataSize);
+}
+
+/**
+  Find free spi protect register and write to it to protect a flash region.
+
+  @param   DirectValue      Value to directly write to register.
+                            if DirectValue == 0 the use Base & Length below.
+  @param   BaseAddress      Base address of region in Flash Memory Map.
+  @param   Length           Length of region to protect.
+
+  @retval  EFI_SUCCESS      Free spi protect register found & written.
+  @retval  EFI_NOT_FOUND    Free Spi protect register not found.
+  @retval  EFI_DEVICE_ERROR Unable to write to spi protect register.
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+  IN CONST UINT32                         DirectValue,
+  IN CONST UINT32                         BaseAddress,
+  IN CONST UINT32                         Length
+  )
+{
+  UINT32                            FreeOffset;
+  UINT32                            PchRootComplexBar;
+  EFI_STATUS                        Status;
+
+  PchRootComplexBar = QNC_RCRB_BASE;
+
+  Status = WriteFirstFreeSpiProtect (
+             PchRootComplexBar,
+             DirectValue,
+             BaseAddress,
+             Length,
+             &FreeOffset
+             );
+
+  if (!EFI_ERROR (Status)) {
+    S3BootScriptSaveMemWrite (
+      S3BootScriptWidthUint32,
+        (UINTN) (PchRootComplexBar + FreeOffset),
+        1,
+        (VOID *) (UINTN) (PchRootComplexBar + FreeOffset)
+        );
+  }
+
+  return Status;
+}
+
+/**
+  Lock legacy SPI static configuration information.
+
+  Function will assert if unable to lock config.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockConfig (
+  VOID
+  )
+{
+  EFI_STATUS        Status;
+  EFI_SPI_PROTOCOL  *SpiProtocol;
+
+  //
+  // Enable lock of legacy SPI static configuration information.
+  //
+
+  SpiProtocol = LocateSpiProtocol (NULL);  // This routine will not be called in SMM.
+  ASSERT (SpiProtocol != NULL);
+  if (SpiProtocol != NULL) {
+    Status = SpiProtocol->Lock (SpiProtocol);
+
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_INFO, "Platform: Spi Config Locked Down\n"));
+    } else if (Status == EFI_ACCESS_DENIED) {
+      DEBUG ((EFI_D_INFO, "Platform: Spi Config already locked down\n"));
+    } else {
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+}
+
+/**
+  Platform Variable Lock.
+
+  @retval EFI_SUCCESS           Platform Variable Lock successful.
+  @retval EFI_NOT_FOUND         No protocol instances were found that match Protocol and
+                                Registration.
+
+**/
+VOID
+EFIAPI
+PlatformVariableLock (
+  )
+{
+  EFI_STATUS                        Status;
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
+
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = VariableLockProtocol->RequestToLock (
+                                   VariableLockProtocol,
+                                   QUARK_VARIABLE_LOCK_NAME,
+                                   &gQuarkVariableLockGuid
+                                   );
+  ASSERT_EFI_ERROR (Status);
+
+  // Memory Config Data shouldn't be writable when Quark Variable Lock is enabled.
+  Status = VariableLockProtocol->RequestToLock (
+                                   VariableLockProtocol,
+                                   EFI_MEMORY_CONFIG_DATA_NAME,
+                                   &gEfiMemoryConfigDataGuid
+                                   );
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Lock regions and config of SPI flash given the policy for this platform.
+
+  Function will assert if unable to lock regions or config.
+
+  @param   PreBootPolicy    If TRUE do Pre Boot Flash Lock Policy.
+
+**/
+VOID
+EFIAPI
+PlatformFlashLockPolicy (
+  IN CONST BOOLEAN                        PreBootPolicy
+  )
+{
+  EFI_STATUS                        Status;
+  UINT64                            CpuAddressNvStorage;
+  UINT64                            CpuAddressFlashDevice;
+  UINT64                            SpiAddress;
+  EFI_BOOT_MODE                     BootMode;
+  UINTN                             SpiFlashDeviceSize;
+
+  BootMode = GetBootModeHob ();
+
+  SpiFlashDeviceSize = (UINTN) PcdGet32 (PcdSpiFlashDeviceSize);
+  CpuAddressFlashDevice = SIZE_4GB - SpiFlashDeviceSize;
+  DEBUG (
+      (EFI_D_INFO,
+      "Platform:FlashDeviceSize = 0x%08x Bytes\n",
+      SpiFlashDeviceSize)
+      );
+
+  //
+  // If not in update or recovery mode, lock stuff down
+  //
+  if ((BootMode != BOOT_IN_RECOVERY_MODE) && (BootMode != BOOT_ON_FLASH_UPDATE)) {
+
+    //
+    // Lock regions
+    //
+    CpuAddressNvStorage = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);
+
+    //
+    // Lock from start of flash device up to Smi writable flash storage areas.
+    //
+    SpiAddress = 0;
+    if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice))) {
+      DEBUG (
+        (EFI_D_INFO,
+        "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+        (UINTN) SpiAddress, (UINTN)(CpuAddressNvStorage - CpuAddressFlashDevice))
+        );
+      Status = PlatformWriteFirstFreeSpiProtect (
+                  0,
+                  (UINT32) SpiAddress,
+                  (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice)
+                  );
+
+      ASSERT_EFI_ERROR (Status);
+    }
+    //
+    // Move Spi Address to after Smi writable flash storage areas.
+    //
+    SpiAddress = CpuAddressNvStorage - CpuAddressFlashDevice;
+    SpiAddress += ((UINT64) PcdGet32 (PcdFlashNvStorageVariableSize));
+
+    //
+    // Lock from end of OEM area to end of flash part.
+    //
+    if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, SpiFlashDeviceSize - ((UINT32) SpiAddress))) {
+      DEBUG (
+        (EFI_D_INFO,
+        "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
+        (UINTN) SpiAddress,
+        (UINTN) (SpiFlashDeviceSize - ((UINT32) SpiAddress)))
+        );
+      ASSERT (SpiAddress < ((UINT64) SpiFlashDeviceSize));
+      Status = PlatformWriteFirstFreeSpiProtect (
+                  0,
+                  (UINT32) SpiAddress,
+                  SpiFlashDeviceSize - ((UINT32) SpiAddress)
+                  );
+
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  //
+  // Always Lock flash config registers if about to boot a boot option
+  // else lock depending on boot mode.
+  //
+  if (PreBootPolicy || (BootMode != BOOT_ON_FLASH_UPDATE)) {
+    PlatformFlashLockConfig ();
+  }
+
+  //
+  // Enable Quark Variable lock if PreBootPolicy.
+  //
+  if (PreBootPolicy) {
+    PlatformVariableLock ();
+  }
+}
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+  @retval  TRUE    If system booted with recovery Boot Stage1 image.
+  @retval  FALSE   If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+  VOID
+  )
+{
+  ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+  return FALSE;
+}
+

+ 481 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c

@@ -0,0 +1,481 @@
+/** @file
+Helper routines with common PEI / DXE implementation.
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CommonHeader.h"
+#include <Library/I2cLib.h>
+
+CHAR16 *mPlatTypeNameTable[]  = { EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION };
+UINTN mPlatTypeNameTableLen  = ((sizeof(mPlatTypeNameTable)) / sizeof (CHAR16 *));
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+//
+// Routines shared with other souce modules in this component.
+//
+
+EFI_STATUS
+WriteFirstFreeSpiProtect (
+  IN CONST UINT32                         PchRootComplexBar,
+  IN CONST UINT32                         DirectValue,
+  IN CONST UINT32                         BaseAddress,
+  IN CONST UINT32                         Length,
+  OUT UINT32                              *OffsetPtr
+  )
+{
+  UINT32                            RegVal;
+  UINT32                            Offset;
+  UINT32                            StepLen;
+
+  ASSERT (PchRootComplexBar > 0);
+
+  Offset = 0;
+  if (OffsetPtr != NULL) {
+    *OffsetPtr = Offset;
+  }
+  if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) == 0) {
+    Offset = R_QNC_RCRB_SPIPBR0;
+  } else {
+    if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1) == 0) {
+      Offset = R_QNC_RCRB_SPIPBR1;
+    } else {
+      if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2) == 0) {
+        Offset = R_QNC_RCRB_SPIPBR2;
+      }
+    }
+  }
+  if (Offset != 0) {
+    if (DirectValue == 0) {
+      StepLen = ALIGN_VALUE (Length,SIZE_4KB);   // Bring up to 4K boundary.
+      RegVal = BaseAddress + StepLen - 1;
+      RegVal &= 0x00FFF000;                     // Set EDS Protected Range Limit (PRL).
+      RegVal |= ((BaseAddress >> 12) & 0xfff);  // or in EDS Protected Range Base (PRB).
+    } else {
+      RegVal = DirectValue;
+    }
+    //
+    // Enable protection.
+    //
+    RegVal |= B_QNC_RCRB_SPIPBRn_WPE;
+    MmioWrite32 (PchRootComplexBar + Offset, RegVal);
+    if (RegVal == MmioRead32 (PchRootComplexBar + Offset)) {
+      if (OffsetPtr != NULL) {
+        *OffsetPtr = Offset;
+      }
+      return EFI_SUCCESS;
+    }
+    return EFI_DEVICE_ERROR;
+  }
+  return EFI_NOT_FOUND;
+}
+
+//
+// Routines exported by this component.
+//
+
+/**
+  Clear SPI Protect registers.
+
+  @retval EFI_SUCCESS        SPI protect registers cleared.
+  @retval EFI_ACCESS_DENIED  Unable to clear SPI protect registers.
+**/
+
+EFI_STATUS
+EFIAPI
+PlatformClearSpiProtect (
+  VOID
+  )
+{
+  UINT32                            PchRootComplexBar;
+
+  PchRootComplexBar = QNC_RCRB_BASE;
+  //
+  // Check if the SPI interface has been locked-down.
+  //
+  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
+    return EFI_ACCESS_DENIED;
+  }
+  MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0, 0);
+  if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+    return EFI_ACCESS_DENIED;
+  }
+  MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1, 0);
+  if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+    return EFI_ACCESS_DENIED;
+  }
+  MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2, 0);
+  if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
+    return EFI_ACCESS_DENIED;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Determine if an SPI address range is protected.
+
+  @param  SpiBaseAddress  Base of SPI range.
+  @param  Length          Length of SPI range.
+
+  @retval TRUE       Range is protected.
+  @retval FALSE      Range is not protected.
+**/
+BOOLEAN
+EFIAPI
+PlatformIsSpiRangeProtected (
+  IN CONST UINT32                         SpiBaseAddress,
+  IN CONST UINT32                         Length
+  )
+{
+  UINT32                            RegVal;
+  UINT32                            Offset;
+  UINT32                            Limit;
+  UINT32                            ProtectedBase;
+  UINT32                            ProtectedLimit;
+  UINT32                            PchRootComplexBar;
+
+  PchRootComplexBar = QNC_RCRB_BASE;
+
+  if (Length > 0) {
+    Offset = R_QNC_RCRB_SPIPBR0;
+    Limit = SpiBaseAddress + (Length - 1);
+    do {
+      RegVal = MmioRead32 (PchRootComplexBar + Offset);
+      if ((RegVal & B_QNC_RCRB_SPIPBRn_WPE) != 0) {
+        ProtectedBase = (RegVal & 0xfff) << 12;
+        ProtectedLimit = (RegVal & 0x00fff000) + 0xfff;
+        if (SpiBaseAddress >= ProtectedBase && Limit <= ProtectedLimit) {
+          return TRUE;
+        }
+      }
+      if (Offset == R_QNC_RCRB_SPIPBR0) {
+        Offset = R_QNC_RCRB_SPIPBR1;
+      } else if (Offset == R_QNC_RCRB_SPIPBR1) {
+        Offset = R_QNC_RCRB_SPIPBR2;
+      } else {
+        break;
+      }
+    } while (TRUE);
+  }
+  return FALSE;
+}
+
+/**
+  Set Legacy GPIO Level
+
+  @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
+  @param  GpioNum             GPIO bit to change.
+  @param  HighLevel           If TRUE set GPIO High else Set GPIO low.
+
+**/
+VOID
+EFIAPI
+PlatformLegacyGpioSetLevel (
+  IN CONST UINT32       LevelRegOffset,
+  IN CONST UINT32       GpioNum,
+  IN CONST BOOLEAN      HighLevel
+  )
+{
+  UINT32  RegValue;
+  UINT32  GpioBaseAddress;
+  UINT32  GpioNumMask;
+
+  GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+  ASSERT (GpioBaseAddress > 0);
+
+  RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
+  GpioNumMask = (1 << GpioNum);
+  if (HighLevel) {
+    RegValue |= (GpioNumMask);
+  } else {
+    RegValue &= ~(GpioNumMask);
+  }
+  IoWrite32 (GpioBaseAddress + LevelRegOffset, RegValue);
+}
+
+/**
+  Get Legacy GPIO Level
+
+  @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
+  @param  GpioNum             GPIO bit to check.
+
+  @retval TRUE       If bit is SET.
+  @retval FALSE      If bit is CLEAR.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformLegacyGpioGetLevel (
+  IN CONST UINT32       LevelRegOffset,
+  IN CONST UINT32       GpioNum
+  )
+{
+  UINT32  RegValue;
+  UINT32  GpioBaseAddress;
+  UINT32  GpioNumMask;
+
+  GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+  RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
+  GpioNumMask = (1 << GpioNum);
+  return ((RegValue & GpioNumMask) != 0);
+}
+
+
+BOOLEAN
+Pcal9555GetPortRegBit (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST UINT8                          RegBase
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             ReadLength;
+  UINTN                             WriteLength;
+  UINT8                             Data[2];
+  EFI_I2C_DEVICE_ADDRESS            I2cDeviceAddr;
+  EFI_I2C_ADDR_MODE                 I2cAddrMode;
+  UINT8                             *RegValuePtr;
+  UINT8                             GpioNumMask;
+  UINT8                             SubAddr;
+
+  I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;
+  I2cAddrMode = EfiI2CSevenBitAddrMode;
+
+  if (GpioNum < 8) {
+    SubAddr = RegBase;
+    GpioNumMask = (UINT8)(1 << GpioNum);
+  } else {
+    SubAddr = RegBase + 1;
+    GpioNumMask = (UINT8)(1 << (GpioNum - 8));
+  }
+
+  //
+  // Output port value always at 2nd byte in Data variable.
+  //
+  RegValuePtr = &Data[1];
+
+  //
+  // On read entry sub address at 2nd byte, on read exit output
+  // port value in 2nd byte.
+  //
+  Data[1] = SubAddr;
+  WriteLength = 1;
+  ReadLength = 1;
+  Status = I2cReadMultipleByte (
+    I2cDeviceAddr,
+    I2cAddrMode,
+    &WriteLength,
+    &ReadLength,
+    &Data[1]
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Adjust output port bit given callers request.
+  //
+  return ((*RegValuePtr & GpioNumMask) != 0);
+}
+
+VOID
+Pcal9555SetPortRegBit (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST UINT8                          RegBase,
+  IN CONST BOOLEAN                        LogicOne
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             ReadLength;
+  UINTN                             WriteLength;
+  UINT8                             Data[2];
+  EFI_I2C_DEVICE_ADDRESS            I2cDeviceAddr;
+  EFI_I2C_ADDR_MODE                 I2cAddrMode;
+  UINT8                             *RegValuePtr;
+  UINT8                             GpioNumMask;
+  UINT8                             SubAddr;
+
+  I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;
+  I2cAddrMode = EfiI2CSevenBitAddrMode;
+
+  if (GpioNum < 8) {
+    SubAddr = RegBase;
+    GpioNumMask = (UINT8)(1 << GpioNum);
+  } else {
+    SubAddr = RegBase + 1;
+    GpioNumMask = (UINT8)(1 << (GpioNum - 8));
+  }
+
+  //
+  // Output port value always at 2nd byte in Data variable.
+  //
+  RegValuePtr = &Data[1];
+
+  //
+  // On read entry sub address at 2nd byte, on read exit output
+  // port value in 2nd byte.
+  //
+  Data[1] = SubAddr;
+  WriteLength = 1;
+  ReadLength = 1;
+  Status = I2cReadMultipleByte (
+    I2cDeviceAddr,
+    I2cAddrMode,
+    &WriteLength,
+    &ReadLength,
+    &Data[1]
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Adjust output port bit given callers request.
+  //
+  if (LogicOne) {
+    *RegValuePtr = *RegValuePtr | GpioNumMask;
+  } else {
+    *RegValuePtr = *RegValuePtr & ~(GpioNumMask);
+  }
+
+  //
+  // Update register. Sub address at 1st byte, value at 2nd byte.
+  //
+  WriteLength = 2;
+  Data[0] = SubAddr;
+  Status = I2cWriteMultipleByte (
+    I2cDeviceAddr,
+    I2cAddrMode,
+    &WriteLength,
+    Data
+    );
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+Set the direction of Pcal9555 IO Expander GPIO pin.
+
+@param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+@param  GpioNum            Gpio direction to configure - values 0-7 for Port0
+and 8-15 for Port1.
+@param  CfgAsInput         If TRUE set pin direction as input else set as output.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioSetDir (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST BOOLEAN                        CfgAsInput
+  )
+{
+  Pcal9555SetPortRegBit (
+    Pcal9555SlaveAddr,
+    GpioNum,
+    PCAL9555_REG_CFG_PORT0,
+    CfgAsInput
+    );
+}
+
+/**
+Set the level of Pcal9555 IO Expander GPIO high or low.
+
+@param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+@param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+for Port1.
+@param  HighLevel          If TRUE set pin high else set pin low.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioSetLevel (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum,
+  IN CONST BOOLEAN                        HighLevel
+  )
+{
+  Pcal9555SetPortRegBit (
+    Pcal9555SlaveAddr,
+    GpioNum,
+    PCAL9555_REG_OUT_PORT0,
+    HighLevel
+    );
+}
+
+/**
+
+Enable pull-up/pull-down resistors of Pcal9555 GPIOs.
+
+@param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+@param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+for Port1.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioEnablePull (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  )
+{
+  Pcal9555SetPortRegBit (
+    Pcal9555SlaveAddr,
+    GpioNum,
+    PCAL9555_REG_PULL_EN_PORT0,
+    TRUE
+    );
+}
+
+/**
+
+Disable pull-up/pull-down resistors of Pcal9555 GPIOs.
+
+@param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+@param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+for Port1.
+
+**/
+VOID
+EFIAPI
+PlatformPcal9555GpioDisablePull (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  )
+{
+  Pcal9555SetPortRegBit (
+    Pcal9555SlaveAddr,
+    GpioNum,
+    PCAL9555_REG_PULL_EN_PORT0,
+    FALSE
+    );
+}
+
+/**
+
+Get state of Pcal9555 GPIOs.
+
+@param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
+@param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
+for Port1.
+
+@retval TRUE               GPIO pin is high
+@retval FALSE              GPIO pin is low
+**/
+BOOLEAN
+EFIAPI
+PlatformPcal9555GpioGetState (
+  IN CONST UINT32                         Pcal9555SlaveAddr,
+  IN CONST UINT32                         GpioNum
+  )
+{
+  return Pcal9555GetPortRegBit (Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_IN_PORT0);
+}
+
+

+ 159 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperPei.c

@@ -0,0 +1,159 @@
+/** @file
+Implementation of Helper routines for PEI enviroment.
+
+Copyright (c) 2013-2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/I2cLib.h>
+
+#include "CommonHeader.h"
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+//
+// Routines exported by this source module.
+//
+
+/**
+  Find pointer to RAW data in Firmware volume file.
+
+  @param   FvNameGuid       Firmware volume to search. If == NULL search all.
+  @param   FileNameGuid     Firmware volume file to search for.
+  @param   SectionData      Pointer to RAW data section of found file.
+  @param   SectionDataSize  Pointer to UNITN to get size of RAW data.
+
+  @retval  EFI_SUCCESS            Raw Data found.
+  @retval  EFI_INVALID_PARAMETER  FileNameGuid == NULL.
+  @retval  EFI_NOT_FOUND          Firmware volume file not found.
+  @retval  EFI_UNSUPPORTED        Unsupported in current enviroment (PEI or DXE).
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFindFvFileRawDataSection (
+  IN CONST EFI_GUID                 *FvNameGuid OPTIONAL,
+  IN CONST EFI_GUID                 *FileNameGuid,
+  OUT VOID                          **SectionData,
+  OUT UINTN                         *SectionDataSize
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             Instance;
+  EFI_PEI_FV_HANDLE                 VolumeHandle;
+  EFI_PEI_FILE_HANDLE               FileHandle;
+  EFI_SECTION_TYPE                  SearchType;
+  EFI_FV_INFO                       VolumeInfo;
+  EFI_FV_FILE_INFO                  FileInfo;
+
+  if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *SectionData = NULL;
+  *SectionDataSize = 0;
+
+  SearchType = EFI_SECTION_RAW;
+  for (Instance = 0; !EFI_ERROR((PeiServicesFfsFindNextVolume (Instance, &VolumeHandle))); Instance++) {
+    if (FvNameGuid != NULL) {
+      Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+      if (!CompareGuid (FvNameGuid, &VolumeInfo.FvName)) {
+        continue;
+      }
+    }
+    Status = PeiServicesFfsFindFileByName (FileNameGuid, VolumeHandle, &FileHandle);
+    if (!EFI_ERROR (Status)) {
+      Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+      if (IS_SECTION2(FileInfo.Buffer)) {
+        *SectionDataSize = SECTION2_SIZE(FileInfo.Buffer) - sizeof(EFI_COMMON_SECTION_HEADER2);
+      } else {
+        *SectionDataSize = SECTION_SIZE(FileInfo.Buffer) - sizeof(EFI_COMMON_SECTION_HEADER);
+      }
+      Status = PeiServicesFfsFindSectionData (SearchType, FileHandle, SectionData);
+      if (!EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Find free spi protect register and write to it to protect a flash region.
+
+  @param   DirectValue      Value to directly write to register.
+                            if DirectValue == 0 the use Base & Length below.
+  @param   BaseAddress      Base address of region in Flash Memory Map.
+  @param   Length           Length of region to protect.
+
+  @retval  EFI_SUCCESS      Free spi protect register found & written.
+  @retval  EFI_NOT_FOUND    Free Spi protect register not found.
+  @retval  EFI_DEVICE_ERROR Unable to write to spi protect register.
+**/
+EFI_STATUS
+EFIAPI
+PlatformWriteFirstFreeSpiProtect (
+  IN CONST UINT32                         DirectValue,
+  IN CONST UINT32                         BaseAddress,
+  IN CONST UINT32                         Length
+  )
+{
+  return WriteFirstFreeSpiProtect (
+           QNC_RCRB_BASE,
+           DirectValue,
+           BaseAddress,
+           Length,
+           NULL
+           );
+}
+
+/** Check if System booted with recovery Boot Stage1 image.
+
+  @retval  TRUE    If system booted with recovery Boot Stage1 image.
+  @retval  FALSE   If system booted with normal stage1 image.
+
+**/
+BOOLEAN
+EFIAPI
+PlatformIsBootWithRecoveryStage1 (
+  VOID
+  )
+{
+  BOOLEAN                           IsRecoveryBoot;
+  QUARK_EDKII_STAGE1_HEADER         *Edk2ImageHeader;
+
+  Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) PcdGet32 (PcdEsramStage1Base);
+  switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
+  case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
+    //
+    // Recovery Boot
+    //
+    IsRecoveryBoot = TRUE;
+    break;
+  default:
+    //
+    // Normal Boot
+    //
+    IsRecoveryBoot = FALSE;
+    break;
+  }
+
+  return IsRecoveryBoot;
+}

+ 146 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformLeds.c

@@ -0,0 +1,146 @@
+/** @file
+Platform helper LED routines.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include "CommonHeader.h"
+
+//
+// Routines defined in other source modules of this component.
+//
+
+//
+// Routines local to this source module.
+//
+
+VOID
+GalileoGen2RouteOutFlashUpdateLed (
+  VOID
+  )
+{
+  //
+  // For GpioNums below values 0 to 7 are for Port0 ie P0-0 - P0-7 and
+  // values 8 to 15 are for Port1 ie P1-0 - P1-7.
+  //
+
+  //
+  // Disable Pull-ups / pull downs on EXP0 pin for LVL_B_PU7 signal.
+  //
+  PlatformPcal9555GpioDisablePull (
+    GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR,  // IO Expander 0.
+    15                                   // P1-7.
+    );
+
+  //
+  // Make LVL_B_OE7_N an output pin.
+  //
+  PlatformPcal9555GpioSetDir (
+    GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR,  // IO Expander 0.
+    14,                                   // P1-6.
+    FALSE
+    );
+
+  //
+  // Set level of LVL_B_OE7_N to low.
+  //
+  PlatformPcal9555GpioSetLevel (
+    GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR,
+    14,
+    FALSE
+    );
+
+  //
+  // Make MUX8_SEL an output pin.
+  //
+  PlatformPcal9555GpioSetDir (
+    GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.
+    14,                                   // P1-6.
+    FALSE
+    );
+
+  //
+  // Set level of MUX8_SEL to low to route GPIO_SUS<5> to LED.
+  //
+  PlatformPcal9555GpioSetLevel (
+    GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.
+    14,                                   // P1-6.
+    FALSE
+    );
+}
+
+//
+// Routines exported by this source module.
+//
+
+/**
+  Init platform LEDs into known state.
+
+  @param   PlatformType     Executing platform type.
+  @param   I2cBus           Pointer to I2c Host controller protocol.
+
+  @retval  EFI_SUCCESS      Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformLedInit (
+  IN CONST EFI_PLATFORM_TYPE              Type
+  )
+{
+  EFI_BOOT_MODE             BootMode;
+
+  BootMode = GetBootModeHob ();
+
+  //
+  // Init Flash update / recovery LED in OFF state.
+  //
+  if (BootMode == BOOT_ON_FLASH_UPDATE || BootMode == BOOT_IN_RECOVERY_MODE) {
+    if (Type == GalileoGen2) {
+      PlatformLegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO, FALSE);
+      GalileoGen2RouteOutFlashUpdateLed ();
+    } else if (Type == Galileo) {
+      PlatformLegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_FLASH_UPDATE_LED_RESUMEWELL_GPIO, FALSE);
+    } else {
+      //
+      // These platforms have no flash update LED.
+      //
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Turn on or off platform flash update LED.
+
+  @param   PlatformType     Executing platform type.
+  @param   TurnOn           If TRUE turn on else turn off.
+
+  @retval  EFI_SUCCESS      Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformFlashUpdateLed (
+  IN CONST EFI_PLATFORM_TYPE              Type,
+  IN CONST BOOLEAN                        TurnOn
+  )
+{
+  if (Type == GalileoGen2) {
+    PlatformLegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO, TurnOn);
+  } else if (Type == Galileo) {
+    PlatformLegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_FLASH_UPDATE_LED_RESUMEWELL_GPIO, TurnOn);
+  } else {
+    //
+    // These platforms have no flash update LED.
+    //
+  }
+
+  return EFI_SUCCESS;
+}

+ 55 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/CommonHeader.h

@@ -0,0 +1,55 @@
+/** @file
+Common header file shared by all source files in this component.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/IntelQNCLib.h>
+#include <IntelQNCRegs.h>
+#include <IntelQNCConfig.h>
+#include <Pcal9555.h>
+#include <Platform.h>
+#include <PlatformBoards.h>
+
+#include <Library/PlatformPcieHelperLib.h>
+
+//
+// Routines shared between souce modules in this component.
+//
+
+VOID
+EFIAPI
+PlatformPcieErratas (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+SocUnitEarlyInitialisation (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPreWaitPllLock (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  );
+
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPostPllLock (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  );
+
+#endif

+ 114 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.c

@@ -0,0 +1,114 @@
+/** @file
+Platform Pcie Helper Lib.
+
+Copyright (c) 2013 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CommonHeader.h"
+
+//
+// Routines local to this source module.
+//
+VOID
+LegacyGpioSetLevel (
+  IN CONST UINT32                         LevelRegOffset,
+  IN CONST UINT32                         GpioNum,
+  IN CONST BOOLEAN                        HighLevel
+  )
+{
+  UINT32                            RegValue;
+  UINT32                            GpioBaseAddress;
+  UINT32                            GpioNumMask;
+
+  GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
+  ASSERT (GpioBaseAddress > 0);
+
+  RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
+  GpioNumMask = (1 << GpioNum);
+  if (HighLevel) {
+    RegValue |= (GpioNumMask);
+  } else {
+    RegValue &= ~(GpioNumMask);
+  }
+  IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, RegValue);
+}
+
+//
+// Routines exported by this component.
+//
+
+/**
+  Platform assert PCI express PERST# signal.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTAssert (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  )
+{
+  if (PlatformType == GalileoGen2) {
+    LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO, FALSE);
+  } else {
+    LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, PCIEXP_PERST_RESUMEWELL_GPIO, FALSE);
+  }
+}
+
+/**
+  Platform de assert PCI express PERST# signal.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+**/
+VOID
+EFIAPI
+PlatformPERSTDeAssert (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  )
+{
+  if (PlatformType == GalileoGen2) {
+    LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_GEN2_PCIEXP_PERST_RESUMEWELL_GPIO, TRUE);
+  } else {
+    LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, PCIEXP_PERST_RESUMEWELL_GPIO, TRUE);
+  }
+}
+
+/** Early initialisation of the PCIe controller.
+
+  @param   PlatformType     See EFI_PLATFORM_TYPE enum definitions.
+
+  @retval   EFI_SUCCESS               Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPciExpressEarlyInit (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  )
+{
+
+  //
+  // Release and wait for PCI controller to come out of reset.
+  //
+  SocUnitReleasePcieControllerPreWaitPllLock (PlatformType);
+  MicroSecondDelay (PCIEXP_DELAY_US_WAIT_PLL_LOCK);
+  SocUnitReleasePcieControllerPostPllLock (PlatformType);
+
+  //
+  // Early PCIe initialisation
+  //
+  SocUnitEarlyInitialisation ();
+
+  //
+  // Do North cluster early PCIe init.
+  //
+  PciExpressEarlyInit ();
+
+  return EFI_SUCCESS;
+}
+

+ 41 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf

@@ -0,0 +1,41 @@
+## @file
+# Library producing Pci Express Helper routines.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformPcieHelperLib
+  FILE_GUID                      = C153F460-5D8A-4d44-83BB-A8AF5CEF132C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformPcieHelperLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformPcieHelperLib.c
+  SocUnit.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  DebugLib
+  TimerLib
+  QNCAccessLib
+  IntelQNCLib

+ 125 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformPcieHelperLib/SocUnit.c

@@ -0,0 +1,125 @@
+/** @file
+System On Chip Unit (SOCUnit) routines.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CommonHeader.h"
+
+/** Early initialisation of the SOC Unit
+
+  @retval   EFI_SUCCESS               Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitEarlyInitialisation (
+  VOID
+  )
+{
+  UINT32      NewValue;
+
+  //
+  // Set the mixer load resistance
+  //
+  NewValue = QNCPortIORead (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0);
+  NewValue &= OCFGPIMIXLOAD_1_0_MASK;
+  QNCPortIOWrite (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0, NewValue);
+
+  NewValue = QNCPortIORead (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1);
+  NewValue &= OCFGPIMIXLOAD_1_0_MASK;
+  QNCPortIOWrite (QUARK_SC_PCIE_AFE_SB_PORT_ID, QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1, NewValue);
+
+  return EFI_SUCCESS;
+}
+
+/** Tasks to release PCI controller from reset pre wait for PLL Lock.
+
+  @retval   EFI_SUCCESS               Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPreWaitPllLock (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  )
+{
+  UINT32      NewValue;
+
+  //
+  // Assert PERST# and validate time assertion time.
+  //
+  PlatformPERSTAssert (PlatformType);
+  ASSERT (PCIEXP_PERST_MIN_ASSERT_US <= (PCIEXP_DELAY_US_POST_CMNRESET_RESET + PCIEXP_DELAY_US_WAIT_PLL_LOCK + PCIEXP_DELAY_US_POST_SBI_RESET));
+
+  //
+  // PHY Common lane reset.
+  //
+  NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+  NewValue |= SOCCLKEN_CONFIG_PHY_I_CMNRESET_L;
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+  //
+  // Wait post common lane reset.
+  //
+  MicroSecondDelay (PCIEXP_DELAY_US_POST_CMNRESET_RESET);
+
+  //
+  // PHY Sideband interface reset.
+  // Controller main reset
+  //
+  NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+  NewValue |= (SOCCLKEN_CONFIG_SBI_RST_100_CORE_B | SOCCLKEN_CONFIG_PHY_I_SIDE_RST_L);
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+  return EFI_SUCCESS;
+}
+
+/** Tasks to release PCI controller from reset after PLL has locked
+
+  @retval   EFI_SUCCESS               Operation success.
+
+**/
+EFI_STATUS
+EFIAPI
+SocUnitReleasePcieControllerPostPllLock (
+  IN CONST EFI_PLATFORM_TYPE              PlatformType
+  )
+{
+  UINT32 NewValue;
+
+  //
+  // Controller sideband interface reset.
+  //
+  NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+  NewValue |= SOCCLKEN_CONFIG_SBI_BB_RST_B;
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+  //
+  // Wait post sideband interface reset.
+  //
+  MicroSecondDelay (PCIEXP_DELAY_US_POST_SBI_RESET);
+
+  //
+  // Deassert PERST#.
+  //
+  PlatformPERSTDeAssert (PlatformType);
+
+  //
+  // Wait post de assert PERST#.
+  //
+  MicroSecondDelay (PCIEXP_DELAY_US_POST_PERST_DEASSERT);
+
+  //
+  // Controller primary interface reset.
+  //
+  NewValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG);
+  NewValue |= SOCCLKEN_CONFIG_BB_RST_B;
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG, NewValue);
+
+  return EFI_SUCCESS;
+}
+

+ 796 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S

@@ -0,0 +1,796 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2013 - 2016 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# Module Name:
+#
+#  Flat32.S
+#
+# Abstract:
+#
+#  This is the code that goes from real-mode to protected mode.
+#  It consumes the reset vector, configures the stack.
+#
+#
+#------------------------------------------------------------------------------
+
+.macro RET32
+    jmp    *%esp
+.endm
+
+#
+# ROM/SPI/MEMORY Definitions
+#
+.equ  QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000)    # Memory Base Address = 0
+.equ  QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000)    # DDR3 Memory Size = 2GB
+.equ  QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000)    # eSRAM Memory Size = 512K
+.equ  QUARK_STACK_SIZE_BYTES, (0x008000)      # Quark stack size = 32K
+
+#
+# RTC/CMOS definitions
+#
+.equ  RTC_INDEX, (0x70)
+.equ    NMI_DISABLE, (0x80)  # Bit7=1 disables NMI
+.equ    NMI_ENABLE, (0x00)  # Bit7=0 disables NMI
+.equ  RTC_DATA, (0x71)
+
+#
+# PCI Configuration definitions
+#
+.equ  PCI_CFG, (0x80000000) # PCI configuration access mechanism
+.equ  PCI_ADDRESS_PORT, (0xCF8)
+.equ  PCI_DATA_PORT, (0xCFC)
+
+#
+# Quark PCI devices
+#
+.equ  HOST_BRIDGE_PFA, (0x0000)   # B0:D0:F0 (Host Bridge)
+.equ  ILB_PFA, (0x00F8)      # B0:D31:F0 (Legacy Block)
+
+#
+# ILB PCI Config Registers
+#
+.equ  BDE, (0x0D4)                                # BIOS Decode Enable register
+.equ    DECODE_ALL_REGIONS_ENABLE, (0xFF000000)    # Decode all BIOS decode ranges
+
+#
+# iLB Reset Register
+#
+.equ  ILB_RESET_REG, (0x0CF9)
+.equ    CF9_WARM_RESET, (0x02)
+.equ    CF9_COLD_RESET, (0x08)
+
+#
+# Host Bridge PCI Config Registers
+#
+.equ  MESSAGE_BUS_CONTROL_REG, (0xD0)       # Message Bus Control Register
+.equ    SB_OPCODE_FIELD, (0x18)              # Bit location of Opcode field
+.equ      OPCODE_SIDEBAND_REG_READ, (0x10)  # Read opcode
+.equ      OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
+.equ      OPCODE_SIDEBAND_ALT_REG_READ, (0x06)  # Alternate Read opcode
+.equ      OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
+.equ      OPCODE_WARM_RESET_REQUEST, (0xF4)  # Reset Warm
+.equ      OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
+.equ    SB_PORT_FIELD, (0x10)               # Bit location of Port ID field
+.equ      MEMORY_ARBITER_PORT_ID, (0x00)
+.equ      HOST_BRIDGE_PORT_ID, (0x03)
+.equ      RMU_PORT_ID, (0x04)
+.equ      MEMORY_MANAGER_PORT_ID, (0x05)
+.equ      SOC_UNIT_PORT_ID, (0x31)
+.equ    SB_ADDR_FIELD, (0x08)               # Bit location of Register field
+.equ    SB_BE_FIELD, (0x04)                  # Bit location of Byte Enables field
+.equ      ALL_BYTE_EN, (0x0F)                # All Byte Enables
+.equ  MESSAGE_DATA_REG, (0xD4)              # Message Data Register
+
+#
+# Memory Arbiter Config Registers
+#
+.equ  AEC_CTRL_OFFSET, (0x00)
+
+#
+# Host Bridge Config Registers
+#
+.equ  HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
+.equ    OR_PM_FIELD, (0x10)
+.equ      SMI_EN, (0x00080000)
+
+.equ  HMBOUND_OFFSET, (0x08)
+.equ    HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+.equ    HMBOUND_LOCK, (0x01)
+.equ  HECREG_OFFSET, (0x09)
+.equ    EC_BASE, (0xE0000000)
+.equ    EC_ENABLE, (0x01)
+.equ  HLEGACY_OFFSET, (0x0A)
+.equ    NMI, (0x00004000)
+.equ    SMI, (0x00001000)
+.equ    INTR, (0x00000400)
+
+#
+# Memory Manager Config Registers
+#
+.equ  ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
+.equ    BLOCK_ENABLE_PG, (0x10000000)
+.equ  BIMRVCTL_OFFSET, (0x19)
+.equ    ENABLE_IMR_INTERRUPT, (0x80000000)
+
+#
+# SOC UNIT Debug Registers
+#
+.equ  CFGSTICKY_W1_OFFSET, (0x50)
+.equ    FORCE_COLD_RESET, (0x00000001)
+.equ  CFGSTICKY_RW_OFFSET, (0x51)
+.equ    RESET_FOR_ESRAM_LOCK, (0x00000020)
+.equ    RESET_FOR_HMBOUND_LOCK, (0x00000040)
+.equ  CFGNONSTICKY_W1_OFFSET, (0x52)
+.equ    FORCE_WARM_RESET, (0x00000001)
+
+#
+# CR0 cache control bit definition
+#
+.equ                    CR0_CACHE_DISABLE, 0x040000000
+.equ                    CR0_NO_WRITE,      0x020000000
+
+ASM_GLOBAL  ASM_PFX(PcdGet32(PcdEsramStage1Base))
+
+
+#
+# Contrary to the name, this file contains 16 bit code as well.
+#
+.text
+#----------------------------------------------------------------------------
+#
+# Procedure:    _ModuleEntryPoint
+#
+# Input:        None
+#
+# Output:       None
+#
+# Destroys:     Assume all registers
+#
+# Description:
+#
+#   Transition to non-paged flat-model protected mode from a
+#   hard-coded GDT that provides exactly two descriptors.
+#   This is a bare bones transition to protected mode only
+#   used for a while in PEI and possibly DXE.
+#
+#   After enabling protected mode, a far jump is executed to
+#   transfer to PEI using the newly loaded GDT.
+#
+# Return:       None
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+  #
+  # Warm Reset (INIT#) check.
+  #
+  .byte   0xbe,0x00,0xf0   #movw    $0xF000, %si
+  .byte   0x8e,0xde        #movw    %si, %ds
+  .byte   0xbe,0xf0,0xff   #movw    $0xFFF0, %si
+  .byte   0x80,0x3c,0xea   #cmpb    $0xEA, (%si)          # Is it warm reset ?
+  jne     NotWarmReset     # Jump if not.
+  .byte   0xb0,0x08        #movb    $0x08, %al
+  .byte   0xba,0xf9,0x0c   #movw    $0xcf9, %dx
+  .byte   0xee             #outb    %al, %dx
+  .byte   0xb0,0x55        #movb    $0x55, %al
+  .byte   0xe6,0x80        #outb    %al, $0x80
+  jmp     .
+NotWarmReset:
+  .byte   0x66,0x8b,0xe8   #movl    %eax, %ebp
+
+  #
+  # Load the GDT table in GdtDesc
+  #
+  .byte   0x66,0xbe        #movl    $GdtDesc, %esi
+  .long   GdtDesc
+
+  .byte   0x66,0x2e,0x0f,0x01,0x14   #lgdt    %cs:(%si)
+
+  #
+  # Transition to 16 bit protected mode
+  #
+  .byte   0x0f,0x20,0xc0       #movl    %cr0, %eax                  # Get control register 0
+  .byte   0x66,0x83,0xc8,0x03  #orl     $0x0000003, %eax           # Set PE bit (bit #0) & MP bit (bit #1)
+  .byte   0x0f,0x22,0xc0       #movl    %eax, %cr0                  # Activate protected mode
+
+  #
+  # Now we're in 16 bit protected mode
+  # Set up the selectors for 32 bit protected mode entry
+  #
+  .byte   0xb8                 #movw    SYS_DATA_SEL, %ax
+  .word   SYS_DATA_SEL
+
+  .byte   0x8e,0xd8            #movw    %ax, %ds
+  .byte   0x8e,0xc0            #movw    %ax, %es
+  .byte   0x8e,0xe0            #movw    %ax, %fs
+  .byte   0x8e,0xe8            #movw    %ax, %gs
+  .byte   0x8e,0xd0            #movw    %ax, %ss
+
+  #
+  # Transition to Flat 32 bit protected mode
+  # The jump to a far pointer causes the transition to 32 bit mode
+  #
+  .byte   0x66,0xbe            #movl   ProtectedModeEntryLinearAddress, %esi
+  .long   ProtectedModeEntryLinearAddress
+  .byte   0x66,0x2e,0xff,0x2c  #jmp    %cs:(%esi)
+
+#
+# Protected mode portion initializes stack, configures cache, and calls C entry point
+#
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    ProtectedModeEntryPoint
+#
+# Input:        Executing in 32 Bit Protected (flat) mode
+#                cs: 0-4GB
+#                ds: 0-4GB
+#                es: 0-4GB
+#                fs: 0-4GB
+#                gs: 0-4GB
+#                ss: 0-4GB
+#
+# Output:       This function never returns
+#
+# Destroys:
+#               ecx
+#               edi
+#                esi
+#                esp
+#
+# Description:
+#                Perform any essential early platform initilaisation
+#               Setup a stack
+#               Transfer control to EDKII code in eSRAM
+#
+#----------------------------------------------------------------------------
+ProtectedModeEntryPoint:
+  leal  L0, %esp
+  jmp  stackless_EarlyPlatformInit
+L0:
+
+  #
+  # Set up stack pointer
+  #
+  movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp
+  movl    $QUARK_ESRAM_MEM_SIZE_BYTES, %esi
+  addl    %esi, %esp                          # ESP = top of stack (stack grows downwards).
+
+  #
+  # Store the the BIST value in EBP
+  #
+  movl    $0, %ebp    # No processor BIST on Quark
+
+  #
+  # Push processor count to stack first, then BIST status (AP then BSP)
+  #
+  movl    $1, %eax
+  cpuid
+  shrl    $16, %ebx
+  andl    $0x000000FF, %ebx
+  cmpb    $1, %bl
+  jae     PushProcessorCount
+
+  #
+  # Some processors report 0 logical processors.  Effectively 0 = 1.
+  # So we fix up the processor count
+  #
+  incl    %ebx
+
+PushProcessorCount:
+  pushl   %ebx
+
+  #
+  # We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
+  # for all processor threads
+  #
+  xorl    %ecx, %ecx
+  movb    %bl, %cl
+
+PushBist:
+  pushl   %ebp
+  loop    PushBist
+
+  #
+  # Pass Control into the PEI Core
+  #
+  call PlatformSecLibStartup
+
+  #
+  # PEI Core should never return to here, this is just to capture an invalid return.
+  #
+  jmp     .
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    stackless_EarlyPlatformInit
+#
+# Input:        esp - Return address
+#
+# Output:       None
+#
+# Destroys:     Assume all registers
+#
+# Description:
+#        Any early platform initialisation required
+#
+# Return:
+#      None
+#
+#----------------------------------------------------------------------------
+stackless_EarlyPlatformInit:
+
+  #
+  # Save return address
+  #
+  movl  %esp, %ebp
+
+  #
+  # Ensure cache is disabled.
+  #
+  movl %cr0, %eax
+  orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
+  invd
+  movl    %eax, %cr0
+
+  #
+  # Disable NMI operation
+  # Good convention suggests you should read back RTC data port after
+  # accessing the RTC index port.
+  #
+  movb $(NMI_DISABLE), %al
+  movw $(RTC_INDEX), %dx
+  outb %al, %dx
+  movw $(RTC_DATA), %dx
+  inb  %dx, %al
+
+  #
+  # Disable SMI (Disables SMI wire, not SMI messages)
+  #
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L1, %esp
+  jmp  stackless_SideBand_Read
+L1:
+  andl $(~SMI_EN), %eax
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L2, %esp
+  jmp  stackless_SideBand_Write
+L2:
+
+  #
+  # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
+  #
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L3, %esp
+  jmp  stackless_SideBand_Read
+L3:
+  andl $(FORCE_WARM_RESET), %eax
+  jz TestForceColdReset    # Zero means bit clear, we're not requested to warm reset so continue as normal
+  jmp IssueWarmReset
+
+TestForceColdReset:
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L4, %esp
+  jmp  stackless_SideBand_Read
+L4:
+  andl $(FORCE_COLD_RESET), %eax
+  jz TestHmboundLock    # Zero means bit clear, we're not requested to cold reset so continue as normal
+  jmp IssueColdReset
+
+  #
+  # Before setting HMBOUND, check it's not locked
+  #
+TestHmboundLock:
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L5, %esp
+  jmp  stackless_SideBand_Read
+L5:
+  andl $(HMBOUND_LOCK), %eax
+  jz ConfigHmbound  # Zero means bit clear, we have the config we want so continue as normal
+  #
+  # Failed to config - store sticky bit debug
+  #
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L6, %esp
+  jmp  stackless_SideBand_Read
+L6:
+  orl $(RESET_FOR_HMBOUND_LOCK), %eax
+  movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L7, %esp
+  jmp  stackless_SideBand_Write
+L7:
+  jmp IssueWarmReset
+
+  #
+  # Set up the HMBOUND register
+  #
+ConfigHmbound:
+  movl $(HMBOUND_ADDRESS), %eax      # Data (Set HMBOUND location)
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L8, %esp
+  jmp  stackless_SideBand_Write
+L8:
+
+  #
+  # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
+  #
+  movl $(ENABLE_IMR_INTERRUPT), %eax      # Data (Set interrupt enable mask)
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L9, %esp
+  jmp  stackless_SideBand_Write
+L9:
+
+  #
+  # Set eSRAM address
+  #
+  movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax   # Data (Set eSRAM location)
+  shr   $(0x18), %eax
+  addl  $(BLOCK_ENABLE_PG), %eax
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L10, %esp
+  jmp  stackless_SideBand_Write
+L10:
+
+  #
+  # Check that we're not blocked from setting the config that we want.
+  #
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L11, %esp
+  jmp  stackless_SideBand_Read
+L11:
+  andl $(BLOCK_ENABLE_PG), %eax
+  jnz ConfigPci  # Non-zero means bit set, we have the config we want so continue as normal
+  #
+  # Failed to config - store sticky bit debug
+  #
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L12, %esp
+  jmp  stackless_SideBand_Read
+L12:
+  orl $(RESET_FOR_ESRAM_LOCK), %eax     # Set the bit we're interested in
+  movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L13, %esp
+  jmp  stackless_SideBand_Write
+L13:
+  jmp IssueWarmReset
+
+  #
+  # Enable PCIEXBAR
+  #
+ConfigPci:
+  movl $(EC_BASE + EC_ENABLE), %eax      # Data
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L14, %esp
+  jmp  stackless_SideBand_Write
+L14:
+
+  movl $(EC_BASE + EC_ENABLE), %eax      # Data
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L15, %esp
+  jmp  stackless_SideBand_Write
+L15:
+
+  #
+  #  Open up full 8MB SPI decode
+  #
+  movl  $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx  # PCI Configuration address
+  movl $(DECODE_ALL_REGIONS_ENABLE), %eax
+  leal  L16, %esp
+  jmp  stackless_PCIConfig_Write
+L16:
+
+  #
+  # Enable NMI operation
+  # Good convention suggests you should read back RTC data port after
+  # accessing the RTC index port.
+  #
+  movb $(NMI_ENABLE), %al
+  movw $(RTC_INDEX), %dx
+  outb %al, %dx
+  movw $(RTC_DATA), %dx
+  inb  %dx, %al
+
+  #
+  # Clear Host Bridge SMI, NMI, INTR fields
+  #
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L21, %esp
+  jmp  stackless_SideBand_Read
+L21:
+  andl $~(NMI + SMI + INTR), %eax      # Clear NMI, SMI, INTR fields
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
+  leal  L22, %esp
+  jmp  stackless_SideBand_Write
+L22:
+
+  #
+  # Restore return address
+  #
+  movl  %ebp, %esp
+  RET32
+
+IssueWarmReset:
+  #
+  # Issue Warm Reset request to Remote Management Unit via iLB
+  #
+  movw  $(CF9_WARM_RESET), %ax
+  movw  $(ILB_RESET_REG), %dx
+  outw  %ax, %dx
+  jmp  .  # Stay here until we are reset.
+
+IssueColdReset:
+  #
+  # Issue Cold Reset request to Remote Management Unit via iLB
+  #
+  movw  $(CF9_COLD_RESET), %ax
+  movw  $(ILB_RESET_REG), %dx
+  outw  %ax, %dx
+  jmp  .  # Stay here until we are reset.
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    stackless_SideBand_Read
+#
+# Input:        esp - return address
+#                ecx[15:8] - Register offset
+#                ecx[23:16] - Port ID
+#                ecx[31:24] - Opcode
+#
+# Output:       eax - Data read
+#
+# Destroys:
+#                eax
+#                ebx
+#                cl
+#                esi
+#
+# Description:
+#        Perform requested sideband read
+#
+#----------------------------------------------------------------------------
+stackless_SideBand_Read:
+
+  movl  %esp, %esi      # Save the return address
+
+  #
+  # Load the SideBand Packet Register to generate the transaction
+  #
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address
+  movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits
+  xchgl  %ecx, %eax
+  leal  L17, %esp
+  jmp  stackless_PCIConfig_Write
+L17:
+  xchgl  %ecx, %eax
+
+  #
+  # Read the SideBand Data Register
+  #
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address
+  leal  L18, %esp
+  jmp  stackless_PCIConfig_Read
+L18:
+
+  movl  %esi, %esp      # Restore the return address
+  RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    stackless_SideBand_Write
+#
+# Input:        esp - return address
+#                eax - Data
+#                ecx[15:8] - Register offset
+#                ecx[23:16] - Port ID
+#                ecx[31:24] - Opcode
+#
+# Output:       None
+#
+# Destroys:
+#                ebx
+#                cl
+#                esi
+#
+# Description:
+#        Perform requested sideband write
+#
+#
+#----------------------------------------------------------------------------
+stackless_SideBand_Write:
+
+  movl  %esp, %esi      # Save the return address
+
+  #
+  # Load the SideBand Data Register with the data
+  #
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address
+  leal  L19, %esp
+  jmp  stackless_PCIConfig_Write
+L19:
+
+  #
+  # Load the SideBand Packet Register to generate the transaction
+  #
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address
+  movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits
+  xchgl  %ecx, %eax
+  leal  L20, %esp
+  jmp  stackless_PCIConfig_Write
+L20:
+  xchgl  %ecx, %eax
+
+  movl  %esi, %esp      # Restore the return address
+  RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    stackless_PCIConfig_Write
+#
+# Input:        esp - return address
+#                eax - Data to write
+#                ebx - PCI Config Address
+#
+# Output:       None
+#
+# Destroys:
+#                dx
+#
+# Description:
+#        Perform a DWORD PCI Configuration write
+#
+#----------------------------------------------------------------------------
+stackless_PCIConfig_Write:
+
+  #
+  # Write the PCI Config Address to the address port
+  #
+  xchgl  %ebx, %eax
+  movw  $(PCI_ADDRESS_PORT), %dx
+  outl  %eax, %dx
+  xchgl  %ebx, %eax
+
+  #
+  # Write the PCI DWORD Data to the data port
+  #
+  movw  $(PCI_DATA_PORT), %dx
+  outl  %eax, %dx
+
+  RET32
+
+
+#----------------------------------------------------------------------------
+#
+# Procedure:    stackless_PCIConfig_Read
+#
+# Input:        esp - return address
+#                ebx - PCI Config Address
+#
+# Output:       eax - Data read
+#
+# Destroys:
+#                eax
+#                dx
+#
+# Description:
+#        Perform a DWORD PCI Configuration read
+#
+#----------------------------------------------------------------------------
+stackless_PCIConfig_Read:
+
+  #
+  # Write the PCI Config Address to the address port
+  #
+  xchgl  %ebx, %eax
+  movw  $(PCI_ADDRESS_PORT), %dx
+  outl  %eax, %dx
+  xchgl  %ebx, %eax
+
+  #
+  # Read the PCI DWORD Data from the data port
+  #
+  movw  $(PCI_DATA_PORT), %dx
+  inl  %dx, %eax
+
+  RET32
+
+
+#
+# ROM-based Global-Descriptor Table for the Tiano PEI Phase
+#
+.align 16
+#
+# GDT[0]: 000h: Null entry, never used.
+#
+
+GDT_BASE:
+BootGdtTable:
+# null descriptor
+.equ                NULL_SEL, . - GDT_BASE # Selector [0]
+        .word 0         # limit 15:0
+        .word 0         # base 15:0
+        .byte 0         # base 23:16
+        .byte 0         # type
+        .byte 0         # limit 19:16, flags
+        .byte 0         # base 31:24
+
+# linear data segment descriptor
+.equ            LINEAR_SEL, . - GDT_BASE # Selector [0x8]
+        .word 0xFFFF    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0x92      # present, ring 0, data, expand-up, writable
+        .byte 0xCF              # page-granular, 32-bit
+        .byte 0
+
+# linear code segment descriptor
+.equ            LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
+        .word 0xFFFF    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0x9A      # present, ring 0, data, expand-up, writable
+        .byte 0xCF              # page-granular, 32-bit
+        .byte 0
+
+# system data segment descriptor
+.equ            SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
+        .word 0xFFFF    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0x92      # present, ring 0, data, expand-up, writable
+        .byte 0xCF              # page-granular, 32-bit
+        .byte 0
+
+# system code segment descriptor
+.equ            SYS_CODE_SEL, . - GDT_BASE
+        .word 0xFFFF    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0x9A      # present, ring 0, data, expand-up, writable
+        .byte 0xCF              # page-granular, 32-bit
+        .byte 0
+
+# spare segment descriptor
+.equ        SYS16_CODE_SEL, . - GDT_BASE
+        .word 0xffff    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0x0f
+        .byte 0x9b      # present, ring 0, data, expand-up, writable
+        .byte 0         # page-granular, 32-bit
+        .byte 0
+
+# spare segment descriptor
+.equ        SYS16_DATA_SEL, . - GDT_BASE
+        .word 0xffff    # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0x93      # present, ring 0, data, expand-up, not-writable
+        .byte 0         # page-granular, 32-bit
+        .byte 0
+
+# spare segment descriptor
+.equ        SPARE5_SEL, . - GDT_BASE
+        .word 0         # limit 0xFFFFF
+        .word 0         # base 0
+        .byte 0
+        .byte 0         # present, ring 0, data, expand-up, writable
+        .byte 0         # page-granular, 32-bit
+        .byte 0
+.equ        GDT_SIZE, . - GDT_BASE
+
+#
+# GDT Descriptor
+#
+GdtDesc:                                     # GDT descriptor
+       .word    GDT_SIZE - 1
+       .long    BootGdtTable
+
+ProtectedModeEntryLinearAddress:
+ProtectedModeEntryLinearOffset:
+       .long    ProtectedModeEntryPoint
+       .word    LINEAR_CODE_SEL

+ 685 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.asm

@@ -0,0 +1,685 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013-2015 Intel Corporation.
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;  Flat32.asm
+;
+; Abstract:
+;
+;  This is the code that goes from real-mode to protected mode.
+;  It consumes the reset vector, configures the stack.
+;
+;
+;------------------------------------------------------------------------------
+
+
+;
+; Define assembler characteristics
+;
+.586p
+.model flat, c
+
+;
+; Include processor definitions
+;
+
+INCLUDE Platform.inc
+
+
+;
+; CR0 cache control bit definition
+;
+CR0_CACHE_DISABLE       EQU 040000000h
+CR0_NO_WRITE            EQU 020000000h
+
+;
+; External and public declarations
+;  TopOfStack is used by C code
+;  SecStartup is the entry point to the C code
+; Neither of these names can be modified without
+; updating the C code.
+;
+EXTRN   PlatformSecLibStartup: NEAR
+EXTERNDEF   C   PcdGet32 (PcdEsramStage1Base):DWORD
+
+;
+; Contrary to the name, this file contains 16 bit code as well.
+;
+_TEXT_REALMODE      SEGMENT PARA PUBLIC USE16 'CODE'
+                    ASSUME  CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    _ModuleEntryPoint
+;
+; Input:        None
+;
+; Output:       None
+;
+; Destroys:     Assume all registers
+;
+; Description:
+;
+;   Transition to non-paged flat-model protected mode from a
+;   hard-coded GDT that provides exactly two descriptors.
+;   This is a bare bones transition to protected mode only
+;   used for a while in PEI and possibly DXE.
+;
+;   After enabling protected mode, a far jump is executed to
+;   transfer to PEI using the newly loaded GDT.
+;
+; Return:       None
+;
+;----------------------------------------------------------------------------
+align 16
+_ModuleEntryPoint      PROC C PUBLIC
+
+  ;
+  ; Warm Reset (INIT#) check.
+  ;
+  mov     si, 0F000h
+  mov     ds, si
+  mov     si, 0FFF0h
+  cmp     BYTE PTR [si], 0EAh   ; Is it warm reset ?
+  jne     NotWarmReset          ; JIf not.
+
+  mov     al, 08
+  mov     dx, 0cf9h
+  out     dx, al
+  mov     al, 055h
+  out     080h, al;
+  jmp $
+NotWarmReset:
+
+  ;
+  ; Load the GDT table in GdtDesc
+  ;
+  mov     esi, OFFSET GdtDesc
+  db      66h
+  lgdt    fword ptr cs:[si]
+
+  ;
+  ; Transition to 16 bit protected mode
+  ;
+  mov     eax, cr0                   ; Get control register 0
+  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)
+  mov     cr0, eax                   ; Activate protected mode
+
+  ;
+  ; Now we're in 16 bit protected mode
+  ; Set up the selectors for 32 bit protected mode entry
+  ;
+  mov     ax, SYS_DATA_SEL
+  mov     ds, ax
+  mov     es, ax
+  mov     fs, ax
+  mov     gs, ax
+  mov     ss, ax
+
+  ;
+  ; Transition to Flat 32 bit protected mode
+  ; The jump to a far pointer causes the transition to 32 bit mode
+  ;
+  mov esi, offset ProtectedModeEntryLinearAddress
+  jmp     fword ptr cs:[si]
+
+_ModuleEntryPoint   ENDP
+
+_TEXT_REALMODE      ENDS
+
+.code
+;
+; Protected mode portion initializes stack, configures cache, and calls C entry point
+;
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    ProtectedModeEntryPoint
+;
+; Input:        Executing in 32 Bit Protected (flat) mode
+;                cs: 0-4GB
+;                ds: 0-4GB
+;                es: 0-4GB
+;                fs: 0-4GB
+;                gs: 0-4GB
+;                ss: 0-4GB
+;
+; Output:       This function never returns
+;
+; Destroys:
+;               ecx
+;               edi
+;                esi
+;                esp
+;
+; Description:
+;                Perform any essential early platform initilaisation
+;               Setup a stack
+;               Call the main EDKII Sec C code
+;
+;----------------------------------------------------------------------------
+
+ProtectedModeEntryPoint PROC NEAR C PUBLIC
+
+  JMP32  stackless_EarlyPlatformInit
+
+  ;
+  ; Set up stack pointer
+  ;
+  mov     esp, PcdGet32(PcdEsramStage1Base)
+  mov     esi, QUARK_ESRAM_MEM_SIZE_BYTES
+  add     esp, esi                         ; ESP = top of stack (stack grows downwards).
+
+  ;
+  ; Store the the BIST value in EBP
+  ;
+  mov     ebp, 00h        ; No processor BIST on Quark
+
+  ;
+  ; Push processor count to stack first, then BIST status (AP then BSP)
+  ;
+  mov     eax, 1
+  cpuid
+  shr     ebx, 16
+  and     ebx, 0000000FFh
+  cmp     bl, 1
+  jae     PushProcessorCount
+
+  ;
+  ; Some processors report 0 logical processors.  Effectively 0 = 1.
+  ; So we fix up the processor count
+  ;
+  inc     ebx
+
+PushProcessorCount:
+  push    ebx
+
+  ;
+  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
+  ; for all processor threads
+  ;
+  xor     ecx, ecx
+  mov     cl, bl
+PushBist:
+  push    ebp
+  loop    PushBist
+
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  call PlatformSecLibStartup
+
+  ;
+  ; PEI Core should never return to here, this is just to capture an invalid return.
+  ;
+  jmp     $
+
+ProtectedModeEntryPoint ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_EarlyPlatformInit
+;
+; Input:        esp - Return address
+;
+; Output:       None
+;
+; Destroys:
+;                eax
+;                ecx
+;                dx
+;                ebp
+;
+; Description:
+;        Any essential early platform initialisation required:
+;        (1) Disable Cache
+;        (2) Disable NMI's/SMI's
+;        (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)
+;        (4) Setup eSRAM (provide early memory to the system)
+;        (5) Setup PCIEXBAR access mechanism
+;        (6) Open up full SPI flash decode
+;
+;----------------------------------------------------------------------------
+stackless_EarlyPlatformInit  PROC NEAR C PUBLIC
+
+  ;
+  ; Save return address
+  ;
+  mov  ebp, esp
+
+  ;
+  ; Ensure cache is disabled.
+  ;
+  mov     eax, cr0
+  or      eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
+  invd
+  mov     cr0, eax
+
+  ;
+  ; Disable NMI
+  ; Good convention suggests you should read back RTC data port after
+  ; accessing the RTC index port.
+  ;
+  mov  al, NMI_DISABLE
+  mov  dx, RTC_INDEX
+  out  dx, al
+  mov  dx, RTC_DATA
+  in  al, dx
+
+  ;
+  ; Disable SMI (Disables SMI wire, not SMI messages)
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, NOT (SMI_EN)
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  ;
+  ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGNONSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, FORCE_WARM_RESET
+  jz TestForceColdReset    ; Zero means bit clear, we're not requested to warm reset so continue as normal
+  jmp IssueWarmReset
+
+TestForceColdReset:
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, FORCE_COLD_RESET
+  jz TestHmboundLock    ; Zero means bit clear, we're not requested to cold reset so continue as normal
+  jmp IssueColdReset
+
+  ;
+  ; Before setting HMBOUND, check it's not locked
+  ;
+TestHmboundLock:
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, HMBOUND_LOCK
+  jz ConfigHmbound  ; Zero means bit clear, we have the config we want so continue as normal
+  ;
+  ; Failed to config - store sticky bit debug
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  or  eax, RESET_FOR_HMBOUND_LOCK  ; Set the bit we're interested in
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+  jmp IssueWarmReset
+
+  ;
+  ; Set up the HMBOUND register
+  ;
+ConfigHmbound:
+  mov  eax, HMBOUND_ADDRESS    ; Data (Set HMBOUND location)
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  ;
+  ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
+  ;
+  mov  eax, ENABLE_IMR_INTERRUPT        ; Data (Set interrupt enable mask)
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (BIMRVCTL_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  ;
+  ; Set eSRAM address
+  ;
+  mov  eax, PcdGet32 (PcdEsramStage1Base)        ; Data (Set eSRAM location)
+  shr  eax, 18h        ; Data (Set eSRAM location)
+  add eax, BLOCK_ENABLE_PG
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+  ;
+  ; Check that we're not blocked from setting the config that we want.
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, BLOCK_ENABLE_PG
+  jnz ConfigPci  ; Non-zero means bit set, we have the config we want so continue as normal
+  ;
+  ; Failed to config - store sticky bit debug
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  or  eax, RESET_FOR_ESRAM_LOCK  ; Set the bit we're interested in
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+  jmp IssueWarmReset
+
+  ;
+  ; Enable PCIEXBAR
+  ;
+ConfigPci:
+  mov  eax, (EC_BASE + EC_ENABLE)      ; Data
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_ARBITER_PORT_ID SHL SB_PORT_FIELD) OR (AEC_CTRL_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  mov  eax, (EC_BASE + EC_ENABLE)      ; Data
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HECREG_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  ;
+  ;  Open up full 8MB SPI decode
+  ;
+  mov  ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE  ; PCI Configuration address
+  mov eax, DECODE_ALL_REGIONS_ENABLE
+  JMP32  stackless_PCIConfig_Write
+
+  ;
+  ; Enable NMI operation
+  ; Good convention suggests you should read back RTC data port after
+  ; accessing the RTC index port.
+  ;
+  mov al, NMI_ENABLE
+  mov dx, RTC_INDEX
+  out dx, al
+  mov dx, RTC_DATA
+  in  al, dx
+
+  ;
+  ; Clear Host Bridge SMI, NMI, INTR fields
+  ;
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Read
+  and  eax, NOT(NMI + SMI + INTR)  ; Clear NMI, SMI, INTR fields
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
+  JMP32  stackless_SideBand_Write
+
+  ;
+  ; Restore return address
+  ;
+  mov  esp, ebp
+  RET32
+
+IssueWarmReset:
+  ;
+  ; Issue Warm Reset request to Remote Management Unit via iLB
+  ;
+  mov ax, CF9_WARM_RESET
+  mov  dx, ILB_RESET_REG
+  out  dx, ax
+  jmp  $  ; Stay here until we are reset.
+
+IssueColdReset:
+  ;
+  ; Issue Cold Reset request to Remote Management Unit via iLB
+  ;
+  mov ax, CF9_COLD_RESET
+  mov  dx, ILB_RESET_REG
+  out  dx, ax
+  jmp  $  ; Stay here until we are reset.
+
+stackless_EarlyPlatformInit ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_SideBand_Read
+;
+; Input:        esp - return address
+;                ecx[15:8] - Register offset
+;                ecx[23:16] - Port ID
+;                ecx[31:24] - Opcode
+;
+; Output:       eax - Data read
+;
+; Destroys:
+;                eax
+;                ebx
+;                cl
+;                esi
+;
+; Description:
+;        Perform requested sideband read
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Read  PROC NEAR C PUBLIC
+
+  mov  esi, esp        ; Save the return address
+
+  ;
+  ; Load the SideBand Packet Register to generate the transaction
+  ;
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address
+  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits
+  xchg  eax, ecx
+  JMP32  stackless_PCIConfig_Write
+  xchg  eax, ecx
+
+  ;
+  ; Read the SideBand Data Register
+  ;
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG    ; PCI Configuration address
+  JMP32  stackless_PCIConfig_Read
+
+  mov  esp, esi        ; Restore the return address
+  RET32
+
+stackless_SideBand_Read ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_SideBand_Write
+;
+; Input:        esp - return address
+;                eax - Data
+;                ecx[15:8] - Register offset
+;                ecx[23:16] - Port ID
+;                ecx[31:24] - Opcode
+;
+; Output:       None
+;
+; Destroys:
+;                ebx
+;                cl
+;                esi
+;
+; Description:
+;        Perform requested sideband write
+;
+;
+;----------------------------------------------------------------------------
+stackless_SideBand_Write  PROC NEAR C PUBLIC
+
+  mov  esi, esp        ; Save the return address
+
+  ;
+  ; Load the SideBand Data Register with the data
+  ;
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG  ; PCI Configuration address
+  JMP32  stackless_PCIConfig_Write
+
+  ;
+  ; Load the SideBand Packet Register to generate the transaction
+  ;
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address
+  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits
+  xchg  eax, ecx
+  JMP32  stackless_PCIConfig_Write
+  xchg  eax, ecx
+
+  mov  esp, esi        ; Restore the return address
+  RET32
+
+stackless_SideBand_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_PCIConfig_Write
+;
+; Input:        esp - return address
+;                eax - Data to write
+;                ebx - PCI Config Address
+;
+; Output:       None
+;
+; Destroys:
+;                dx
+;
+; Description:
+;        Perform a DWORD PCI Configuration write
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Write  PROC NEAR C PUBLIC
+
+  ;
+  ; Write the PCI Config Address to the address port
+  ;
+  xchg  eax, ebx
+  mov  dx, PCI_ADDRESS_PORT
+  out  dx, eax
+  xchg  eax, ebx
+
+  ;
+  ; Write the PCI DWORD Data to the data port
+  ;
+  mov  dx, PCI_DATA_PORT
+  out  dx, eax
+
+  RET32
+
+stackless_PCIConfig_Write ENDP
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_PCIConfig_Read
+;
+; Input:        esp - return address
+;                ebx - PCI Config Address
+;
+; Output:       eax - Data read
+;
+; Destroys:
+;                eax
+;                dx
+;
+; Description:
+;        Perform a DWORD PCI Configuration read
+;
+;----------------------------------------------------------------------------
+stackless_PCIConfig_Read  PROC NEAR C PUBLIC
+
+  ;
+  ; Write the PCI Config Address to the address port
+  ;
+  xchg  eax, ebx
+  mov  dx, PCI_ADDRESS_PORT
+  out  dx, eax
+  xchg  eax, ebx
+
+  ;
+  ; Read the PCI DWORD Data from the data port
+  ;
+  mov  dx, PCI_DATA_PORT
+  in  eax, dx
+
+  RET32
+
+stackless_PCIConfig_Read ENDP
+
+;
+; ROM-based Global-Descriptor Table for the Tiano PEI Phase
+;
+align 16
+PUBLIC  BootGdtTable
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL        equ     $ - GDT_BASE        ; Selector [0]
+GDT_BASE:
+BootGdtTable    DD      0
+                DD      0
+;
+; Linear data segment descriptor
+;
+LINEAR_SEL      equ     $ - GDT_BASE        ; Selector [0x8]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      092h                        ; present, ring 0, data, expand-up, writable
+        DB      0CFh                        ; page-granular, 32-bit
+        DB      0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL equ     $ - GDT_BASE        ; Selector [0x10]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      09Bh                        ; present, ring 0, data, expand-up, not-writable
+        DB      0CFh                        ; page-granular, 32-bit
+        DB      0
+;
+; System data segment descriptor
+;
+SYS_DATA_SEL    equ     $ - GDT_BASE        ; Selector [0x18]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      093h                        ; present, ring 0, data, expand-up, not-writable
+        DB      0CFh                        ; page-granular, 32-bit
+        DB      0
+
+;
+; System code segment descriptor
+;
+SYS_CODE_SEL    equ     $ - GDT_BASE        ; Selector [0x20]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      09Ah                        ; present, ring 0, data, expand-up, writable
+        DB      0CFh                        ; page-granular, 32-bit
+        DB      0
+;
+; Spare segment descriptor
+;
+SYS16_CODE_SEL  equ     $ - GDT_BASE        ; Selector [0x28]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0Fh
+        DB      09Bh                        ; present, ring 0, code, expand-up, writable
+        DB      00h                         ; byte-granular, 16-bit
+        DB      0
+;
+; Spare segment descriptor
+;
+SYS16_DATA_SEL  equ     $ - GDT_BASE        ; Selector [0x30]
+        DW      0FFFFh                      ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      093h                        ; present, ring 0, data, expand-up, not-writable
+        DB      00h                         ; byte-granular, 16-bit
+        DB      0
+
+;
+; Spare segment descriptor
+;
+SPARE5_SEL      equ     $ - GDT_BASE        ; Selector [0x38]
+        DW      0                           ; limit 0xFFFF
+        DW      0                           ; base 0
+        DB      0
+        DB      0                           ; present, ring 0, data, expand-up, writable
+        DB      0                           ; page-granular, 32-bit
+        DB      0
+GDT_SIZE        EQU     $ - BootGDTtable    ; Size, in bytes
+
+;
+; GDT Descriptor
+;
+GdtDesc:                                    ; GDT descriptor
+        DW      GDT_SIZE - 1                ; GDT limit
+        DD      OFFSET BootGdtTable         ; GDT base address
+
+ProtectedModeEntryLinearAddress   LABEL   FWORD
+ProtectedModeEntryLinearOffset    LABEL   DWORD
+  DD      OFFSET ProtectedModeEntryPoint  ; Offset of our 32 bit code
+  DW      LINEAR_CODE_SEL
+
+END

+ 134 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Platform.inc

@@ -0,0 +1,134 @@
+;
+; Copyright (c) 2013-2015 Intel Corporation.
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+;
+; Module Name:
+;
+;   Platform.inc
+;
+; Abstract:
+;
+;   Quark A0 Platform Specific Definitions
+;
+;------------------------------------------------------------------------------
+
+JMP32 MACRO FunctionName
+  lea  esp, @F
+  jmp  FunctionName
+@@:
+ENDM
+
+RET32 MACRO
+    jmp    esp
+ENDM
+
+;
+; ROM/SPI/MEMORY Definitions
+;
+QUARK_DDR3_MEM_BASE_ADDRESS    EQU 000000000h    ; Memory Base Address = 0
+QUARK_MAX_DDR3_MEM_SIZE_BYTES    EQU 080000000h    ; DDR3 Memory Size = 2GB
+QUARK_ESRAM_MEM_SIZE_BYTES    EQU 000080000h    ; eSRAM Memory Size = 512K
+QUARK_STACK_SIZE_BYTES      EQU 008000h      ; Quark stack size = 32K
+
+;
+; RTC/CMOS definitions
+;
+RTC_INDEX      EQU 070h
+  NMI_DISABLE  EQU 080h    ; Bit7=1 disables NMI
+  NMI_ENABLE  EQU 000h    ; Bit7=0 disables NMI
+RTC_DATA      EQU 071h
+
+;
+; PCI Configuration definitions
+;
+PCI_CFG            EQU 1 SHL 01Fh  ; PCI configuration access mechanism
+PCI_ADDRESS_PORT  EQU 0CF8h
+PCI_DATA_PORT      EQU 0CFCh
+
+;
+; Quark PCI devices
+;
+HOST_BRIDGE_PFA        EQU 0000h          ; B0:D0:F0 (Host Bridge)
+ILB_PFA          EQU 00F8h          ; B0:D31:F0 (Legacy Block)
+
+;
+; ILB PCI Config Registers
+;
+BDE                              EQU 0D4h        ; BIOS Decode Enable register
+  DECODE_ALL_REGIONS_ENABLE      EQU 0FF000000h  ; Decode all BIOS decode ranges
+
+
+;
+; iLB Reset Register
+;
+ILB_RESET_REG      EQU 0CF9h
+  CF9_WARM_RESET    EQU  02h
+  CF9_COLD_RESET    EQU  08h
+
+;
+; Host Bridge PCI Config Registers
+;
+MESSAGE_BUS_CONTROL_REG                    EQU 0D0h  ; Message Bus Control Register
+  SB_OPCODE_FIELD                EQU 018h  ; Bit location of Opcode field
+    OPCODE_SIDEBAND_REG_READ    EQU 010h  ; Read opcode
+    OPCODE_SIDEBAND_REG_WRITE    EQU 011h  ; Write opcode
+    OPCODE_SIDEBAND_ALT_REG_READ  EQU 06h    ; Alternate Read opcode
+    OPCODE_SIDEBAND_ALT_REG_WRITE  EQU 07h    ; Alternate Write opcode
+    OPCODE_WARM_RESET_REQUEST    EQU 0F4h  ; Reset Warm
+    OPCODE_COLD_RESET_REQUEST    EQU 0F5h  ; Reset Cold
+  SB_PORT_FIELD                  EQU 010h  ; Bit location of Port ID field
+    MEMORY_ARBITER_PORT_ID                EQU 00h
+    HOST_BRIDGE_PORT_ID                EQU 03h
+    RMU_PORT_ID                EQU 04h
+    MEMORY_MANAGER_PORT_ID                EQU 05h
+    SOC_UNIT_PORT_ID              EQU  031h
+  SB_ADDR_FIELD                  EQU 008h  ; Bit location of Register field
+  SB_BE_FIELD                    EQU  004h  ; Bit location of Byte Enables field
+    ALL_BYTE_EN                  EQU  00Fh  ; All Byte Enables
+MESSAGE_DATA_REG                      EQU 0D4h  ; Message Data Register
+
+;
+; Memory Arbiter Config Registers
+;
+AEC_CTRL_OFFSET    EQU 00h
+
+;
+; Host Bridge Config Registers
+;
+HMISC2_OFFSET      EQU 03h
+  OR_PM_FIELD      EQU 010h
+    SMI_EN        EQU 1 SHL 13h
+
+HMBOUND_OFFSET    EQU 08h
+  HMBOUND_ADDRESS  EQU (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
+  HMBOUND_LOCK  EQU 00000001h
+HECREG_OFFSET    EQU 09h
+  EC_BASE      EQU 0E0000000h
+  EC_ENABLE    EQU 01h
+HLEGACY_OFFSET    EQU 0Ah
+  NMI              EQU 1 SHL 0Eh  ; Pin 14
+  SMI              EQU 1 SHL 0Ch  ; Pin 12
+  INTR             EQU 1 SHL 0Ah  ; Pin 10
+
+
+;
+; Memory Manager Config Registers
+;
+ESRAMPGCTRL_BLOCK_OFFSET  EQU 082h
+  BLOCK_ENABLE_PG      EQU 010000000h
+BIMRVCTL_OFFSET        EQU 019h
+  ENABLE_IMR_INTERRUPT  EQU 080000000h
+
+;
+; SOC UNIT Debug Registers
+;
+CFGSTICKY_W1_OFFSET          EQU 050h
+  FORCE_COLD_RESET      EQU  00000001h
+CFGSTICKY_RW_OFFSET            EQU 051h
+  RESET_FOR_ESRAM_LOCK    EQU  00000020h
+  RESET_FOR_HMBOUND_LOCK    EQU  00000040h
+CFGNONSTICKY_W1_OFFSET        EQU 052h
+  FORCE_WARM_RESET      EQU  00000001h

+ 207 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLib.c

@@ -0,0 +1,207 @@
+/** @file
+Platform SEC Library for Quark.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TemporaryRamSupport.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/MtrrLib.h>
+
+/**
+
+  Entry point to the C language phase of SEC. After the SEC assembly
+  code has initialized some temporary memory and set up the stack,
+  the control is transferred to this function.
+
+  @param SizeOfRam           Size of the temporary memory available for use.
+  @param TempRamBase         Base address of temporary ram
+  @param BootFirmwareVolume  Base address of the Boot Firmware Volume.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+  IN UINT32                   SizeOfRam,
+  IN UINT32                   TempRamBase,
+  IN VOID                     *BootFirmwareVolume
+  );
+
+/**
+  Auto-generated function that calls the library constructors for all of the module's
+  dependent libraries.  This function must be called by the SEC Core once a stack has
+  been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+  VOID
+  );
+
+/**
+
+  Entry point to the C language phase of PlatformSecLib.  After the SEC assembly
+  code has initialized some temporary memory and set up the stack, control is
+  transferred to this function.
+
+**/
+VOID
+EFIAPI
+PlatformSecLibStartup (
+  VOID
+  )
+{
+  //
+  // Process all library constructor functions linked to SecCore.
+  // This function must be called before any library functions are called
+  //
+  ProcessLibraryConstructorList ();
+
+  //
+  // Set write back cache attribute for SPI FLASH
+  //
+  MtrrSetMemoryAttribute (
+    PcdGet32 (PcdFlashAreaBaseAddress),
+    PcdGet32 (PcdFlashAreaSize),
+    CacheWriteBack
+    );
+
+  //
+  // Set write back cache attribute for 512KB Embedded SRAM
+  //
+  MtrrSetMemoryAttribute (
+    PcdGet32 (PcdEsramStage1Base),
+    SIZE_512KB,
+    CacheWriteBack
+    );
+
+  //
+  // Pass control to SecCore module passing in the size of the temporary RAM in
+  // Embedded SRAM, the base address of the temporary RAM in Embedded SRAM, and
+  // the base address of the boot firmware volume.  The top 32KB of the 512 KB
+  // embedded SRAM are used as temporary RAM.
+  //
+  SecStartup (
+    SIZE_32KB,
+    PcdGet32 (PcdEsramStage1Base) + SIZE_512KB - SIZE_32KB,
+    (VOID *)(UINTN)PcdGet32 (PcdFlashFvRecoveryBase)
+    );
+}
+
+/**
+  A developer supplied function to perform platform specific operations.
+
+  It's a developer supplied function to perform any operations appropriate to a
+  given platform. It's invoked just before passing control to PEI core by SEC
+  core. Platform developer may modify the SecCoreData and PPI list that is
+  passed to PEI Core.
+
+  @param  SecCoreData           The same parameter as passing to PEI core. It
+                                could be overridden by this function.
+  @param  PpiList               The default PPI list passed from generic SEC
+                                part.
+
+  @return The final PPI list that platform wishes to passed to PEI core.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+  IN OUT   EFI_SEC_PEI_HAND_OFF        *SecCoreData,
+  IN       EFI_PEI_PPI_DESCRIPTOR      *PpiList
+  )
+{
+  return NULL;
+}
+
+/**
+  This interface conveys state information out of the Security (SEC) phase into PEI.
+
+  @param  PeiServices               Pointer to the PEI Services Table.
+  @param  StructureSize             Pointer to the variable describing size of the input buffer.
+  @param  PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+  @retval EFI_SUCCESS           The data was successfully returned.
+  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+  IN CONST EFI_PEI_SERVICES                     **PeiServices,
+  IN OUT   UINT64                               *StructureSize,
+     OUT   EFI_SEC_PLATFORM_INFORMATION_RECORD  *PlatformInformationRecord
+  )
+{
+  UINT32             *BIST;
+  UINT32             Size;
+  UINT32             Count;
+  EFI_HOB_GUID_TYPE  *GuidHob;
+  UINT32             *TopOfStack;
+
+  //
+  // Top of the stack is the top of the 512KB Embedded SRAM region
+  //
+  TopOfStack = (UINT32 *)(UINTN)(PcdGet32 (PcdEsramStage1Base) + SIZE_512KB);
+
+  GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
+  if (GuidHob != NULL) {
+    Size = GET_GUID_HOB_DATA_SIZE (GuidHob);
+    BIST = GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    //
+    // The entries of BIST information, together with the number of them,
+    // reside in the bottom of stack, left untouched by normal stack operation.
+    // This routine copies the BIST information to the buffer pointed by
+    // PlatformInformationRecord for output.
+    //
+    Count = *(TopOfStack - 1);
+    Size  = Count * sizeof (IA32_HANDOFF_STATUS);
+    BIST  = (UINT32 *) ((UINT32) TopOfStack - sizeof (UINT32) - Size);
+
+    //
+    // Copy Data from Stack to Hob to avoid data is lost after memory is ready.
+    //
+    BuildGuidDataHob (
+      &gEfiSecPlatformInformationPpiGuid,
+      BIST,
+      (UINTN)Size
+    );
+    GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
+    Size = GET_GUID_HOB_DATA_SIZE (GuidHob);
+    BIST = GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  if ((*StructureSize) < (UINT64) Size) {
+    *StructureSize = Size;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *StructureSize  = Size;
+  CopyMem (PlatformInformationRecord, BIST, Size);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This interface disables temporary memory in SEC Phase.
+**/
+VOID
+EFIAPI
+SecPlatformDisableTemporaryMemory (
+  VOID
+  )
+{
+}

+ 54 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLib.inf

@@ -0,0 +1,54 @@
+#/** @file
+# Platform SEC Library for Quark.
+#
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformSecLib
+  FILE_GUID                      = 8DE4221F-A9CC-4c78-85B9-D863681F0C01
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformSecLib
+  MODULE_UNI_FILE                = PlatformSecLibModStrs.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformSecLib.c
+
+[Sources.IA32]
+  Ia32/Flat32.asm | MSFT
+  Ia32/Flat32.asm | INTEL
+  Ia32/Flat32.S   | GCC
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib
+  BaseMemoryLib
+  PciLib
+  PcdLib
+  HobLib
+  MtrrLib
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdEsramStage1Base         ## CONSUMES
+  gQuarkPlatformTokenSpaceGuid.PcdFlashFvRecoveryBase     ## CONSUMES
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress    ## CONSUMES
+  gQuarkPlatformTokenSpaceGuid.PcdFlashAreaSize           ## CONSUMES
+
+[Ppis]
+  gEfiSecPlatformInformationPpiGuid   ## UNDEFINED # it is used as GUIDED HOB

+ 18 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni

@@ -0,0 +1,18 @@
+// /** @file
+// PlatformSecLib Localized Abstract and Description Content
+//
+// Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT
+#language en-US
+"SEC Platform Library "
+
+#string STR_MODULE_DESCRIPTION
+#language en-US
+"Provides a platform-specific function to be used during the SEC stage of POST. "
+
+

+ 164 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.c

@@ -0,0 +1,164 @@
+/** @file
+Provides a secure platform-specific method to detect physically present user.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/I2cLib.h>
+
+#include <PlatformBoards.h>
+#include <Pcal9555.h>
+#include <QNCAccess.h>
+
+//
+// Global variable to cache pointer to I2C protocol.
+//
+EFI_PLATFORM_TYPE mPlatformType = TypeUnknown;
+
+BOOLEAN
+CheckResetButtonState (
+  VOID
+  )
+{
+  EFI_STATUS              Status;
+  EFI_I2C_DEVICE_ADDRESS  I2CSlaveAddress;
+  UINTN                   Length;
+  UINTN                   ReadLength;
+  UINT8                   Buffer[2];
+
+  DEBUG ((EFI_D_INFO, "CheckResetButtonState(): mPlatformType == %d\n", mPlatformType));
+  if (mPlatformType == GalileoGen2) {
+    //
+    // Read state of Reset Button - EXP2.P1_7
+    // This GPIO is pulled high when the button is not pressed
+    // This GPIO reads low when button is pressed
+    //
+    return PlatformPcal9555GpioGetState (
+      GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.
+      15                                    // P1-7.
+      );
+  }
+  if (mPlatformType == Galileo) {
+    //
+    // Detect the I2C Slave Address of the GPIO Expander
+    //
+    if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
+      I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;
+    } else {
+      I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;
+    }
+    DEBUG ((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress));
+
+    //
+    // Read state of RESET_N_SHLD (GPORT5_BIT0)
+    //
+    Buffer[1] = 5;
+    Length = 1;
+    ReadLength = 1;
+    Status = I2cReadMultipleByte (
+               I2CSlaveAddress,
+               EfiI2CSevenBitAddrMode,
+               &Length,
+               &ReadLength,
+               &Buffer[1]
+               );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Return the state of GPORT5_BIT0
+    //
+    return ((Buffer[1] & BIT0) != 0);
+  }
+  return TRUE;
+}
+
+/**
+
+  This function provides a platform-specific method to detect whether the platform
+  is operating by a physically present user.
+
+  Programmatic changing of platform security policy (such as disable Secure Boot,
+  or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during
+  Boot Services or after exiting EFI Boot Services. Only a physically present user
+  is allowed to perform these operations.
+
+  NOTE THAT: This function cannot depend on any EFI Variable Service since they are
+  not available when this function is called in AuthenticateVariable driver.
+
+  @retval  TRUE       The platform is operated by a physically present user.
+  @retval  FALSE      The platform is NOT operated by a physically present user.
+
+**/
+BOOLEAN
+EFIAPI
+UserPhysicalPresent (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // If user has already been detected as present, then return TRUE
+  //
+  if (PcdGetBool (PcdUserIsPhysicallyPresent)) {
+    return TRUE;
+  }
+
+  //
+  // Check to see if user is present now
+  //
+  if (CheckResetButtonState ()) {
+    //
+    // User is still not present, then return FALSE
+    //
+    return FALSE;
+  }
+
+  //
+  // User has gone from not present to present state, so set
+  // PcdUserIsPhysicallyPresent to TRUE
+  //
+  Status = PcdSetBoolS (PcdUserIsPhysicallyPresent, TRUE);
+  ASSERT_EFI_ERROR (Status);
+
+  return TRUE;
+}
+
+/**
+  Determines if a user is physically present by reading the reset button state.
+
+  @param  ImageHandle  The image handle of this driver.
+  @param  SystemTable  A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   Install the Secure Boot Helper Protocol successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSecureLibInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Get the platform type
+  //
+  mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);
+
+  //
+  // Read the state of the reset button when the library is initialized
+  //
+  Status = PcdSetBoolS (PcdUserIsPhysicallyPresent, !CheckResetButtonState ());
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}

+ 41 - 0
Platform/Intel/QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf

@@ -0,0 +1,41 @@
+## @file
+# Provides a secure platform-specific method to detect physically present user.
+#
+# Copyright (c) 2013 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformSecureLib
+  FILE_GUID                      = 38BB5221-F685-469f-846E-F1C508FC5F4A
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformSecureLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER
+  CONSTRUCTOR                    = PlatformSecureLibInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformSecureLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  QuarkSocPkg/QuarkSocPkg.dec
+  QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  PlatformHelperLib
+  UefiBootServicesTableLib
+  I2cLib
+
+[Pcd]
+  gQuarkPlatformTokenSpaceGuid.PcdPlatformType
+  gQuarkPlatformTokenSpaceGuid.PcdUserIsPhysicallyPresent

Some files were not shown because too many files changed in this diff