summaryrefslogtreecommitdiff
path: root/Silicon/Hisilicon/Drivers
diff options
context:
space:
mode:
authorLeif Lindholm <leif.lindholm@linaro.org>2017-05-03 14:48:15 +0100
committerLeif Lindholm <leif.lindholm@linaro.org>2017-07-14 22:36:50 +0100
commit8322634459ac602d9fbcca30e96b24ff098acb3c (patch)
treefef3287095bb56eba411c0b31c525283978b71fb /Silicon/Hisilicon/Drivers
parentd61262ca0818842c1c3a32d3a4deb8217aee8580 (diff)
downloadedk2-platforms-8322634459ac602d9fbcca30e96b24ff098acb3c.tar.xz
Platform,Silicon: Import Hisilicon D02,D03,D05 and HiKey
Imported from commit efd798c1eb of https://git.linaro.org/uefi/OpenPlatformPkg.git Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Diffstat (limited to 'Silicon/Hisilicon/Drivers')
-rw-r--r--Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c40
-rw-r--r--Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf72
-rw-r--r--Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c508
-rw-r--r--Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h22
-rw-r--r--Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c109
-rw-r--r--Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c1243
-rw-r--r--Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h228
-rw-r--r--Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf69
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c269
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni22
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf62
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni20
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c137
-rw-r--r--Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h16
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c162
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c594
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf64
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c628
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h116
-rw-r--r--Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c1651
-rw-r--r--Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h521
-rw-r--r--Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf74
-rw-r--r--Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c2313
-rw-r--r--Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c1049
-rw-r--r--Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf46
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c205
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h36
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf50
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c762
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h79
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf59
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni30
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c728
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h108
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf64
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni32
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h226
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c58
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf108
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c194
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni28
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni25
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c105
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c258
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni27
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c52
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c195
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni27
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c56
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c198
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni24
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c66
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c199
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.unibin0 -> 1592 bytes
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c162
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c201
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni49
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c46
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c163
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c48
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c74
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c42
-rw-r--r--Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c87
-rw-r--r--Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c158
-rw-r--r--Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf62
-rw-r--r--Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c108
-rw-r--r--Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf53
-rw-r--r--Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c682
-rw-r--r--Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h82
-rw-r--r--Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf60
70 files changed, 16111 insertions, 0 deletions
diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..3d5ae9142a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,40 @@
+/** @file
+
+ Copyright (c) 2014, Applied Micro Curcuit Corporation. All rights reserved.<BR>
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+ Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PiDxe.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/AcpiAml.h>
+#include "EthMac.h"
+
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EthMacInit();
+}
diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..5209f31801
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,72 @@
+## @file
+#
+# Copyright (c) 2014, Applied Micro Curcuit Corp. All rights reserved.<BR>
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+# Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = e0829681-e9fa-4117-a8d7-84efadff863d
+ MODULE_TYPE = DXE_DRIVER
+ #MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+[Sources]
+ AcpiPlatform.c
+ EthMac.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ #UefiApplicationEntryPoint
+
+[Guids]
+ gShellVariableGuid # ALWAYS_CONSUMED
+ gArmMpCoreInfoGuid
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gHisiBoardNicProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol
+
+[Pcd]
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+[Depex]
+ gEfiAcpiTableProtocolGuid AND gEfiAcpiSdtProtocolGuid AND gHisiBoardNicProtocolGuid
+
diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c
new file mode 100644
index 0000000000..1f74d312af
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.c
@@ -0,0 +1,508 @@
+/** @file
+
+ Copyright (c) 2014, Applied Micro Curcuit Corporation. All rights reserved.<BR>
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+ Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ This driver is called to initialize the FW part of the PHY in preparation
+ for the OS.
+
+**/
+
+#include <Guid/ShellVariableGuid.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+
+#include <PiDxe.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/AcpiAml.h>
+
+#include <Protocol/HisiBoardNicProtocol.h>
+
+// Turn on debug message by enabling below define
+//#define ACPI_DEBUG
+
+#ifdef ACPI_DEBUG
+#define DBG(arg...) DEBUG((EFI_D_ERROR,## arg))
+#else
+#define DBG(arg...)
+#endif
+
+#define EFI_ACPI_MAX_NUM_TABLES 20
+#define DSDT_SIGNATURE 0x54445344
+
+#define D02_ACPI_ETH_ID "HISI00C1"
+#define D03_ACPI_ETH_ID "HISI00C2"
+
+#define ACPI_ETH_MAC_KEY "local-mac-address"
+
+#define PREFIX_VARIABLE_NAME L"MAC"
+#define PREFIX_VARIABLE_NAME_COMPAT L"RGMII_MAC"
+#define MAC_MAX_LEN 30
+
+EFI_STATUS GetEnvMac(
+ IN UINTN MacNextID,
+ IN OUT UINT8 *MacBuffer)
+{
+ EFI_MAC_ADDRESS Mac;
+ EFI_STATUS Status;
+ HISI_BOARD_NIC_PROTOCOL *OemNic = NULL;
+
+ Status = gBS->LocateProtocol(&gHisiBoardNicProtocolGuid, NULL, (VOID **)&OemNic);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol failed %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ Status = OemNic->GetMac(&Mac, MacNextID);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] GetMac failed %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ CopyMem (MacBuffer, &Mac, 6);
+ DEBUG((EFI_D_ERROR, "Port %d MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ MacNextID,
+ MacBuffer[0],
+ MacBuffer[1],
+ MacBuffer[2],
+ MacBuffer[3],
+ MacBuffer[4],
+ MacBuffer[5]
+ ));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS _SearchReplacePackageMACAddress(
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ IN EFI_ACPI_HANDLE ChildHandle,
+ IN UINTN Level,
+ IN OUT BOOLEAN *Found,
+ IN UINTN MacNextID)
+{
+ // ASL template for ethernet driver:
+/*
+ * Name (_DSD, Package () {
+ * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ * Package () {
+ * Package (2) {"mac-address", Package (6) { 00, 11, 22, 33, 44, 55 }}
+ * Package (2) {"phy-channel", 0},
+ * Package (2) {"phy-mode", "rgmii"},
+ * Package (2) {"max-transfer-unit", 0x5dc}, // MTU of 1500
+ * Package (2) {"max-speed", 0x3e8}, // 1000 Mbps
+ * }
+ * })
+ */
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ CONST UINT8 *Data;
+ CONST VOID *Buffer;
+ UINTN DataSize;
+ UINTN Count;
+ EFI_ACPI_HANDLE CurrentHandle;
+ EFI_ACPI_HANDLE NextHandle;
+ UINT8 MACBuffer[MAC_MAX_LEN];
+
+ DBG("In Level:%d\n", Level);
+ Status = EFI_SUCCESS;
+ for (CurrentHandle = NULL; ;) {
+ Status = AcpiTableProtocol->GetChild(ChildHandle, &CurrentHandle);
+ if (Level != 3 && (EFI_ERROR(Status) || CurrentHandle == NULL))
+ break;
+
+ Status = AcpiTableProtocol->GetOption(CurrentHandle, 0, &DataType, &Buffer, &DataSize);
+ Data = Buffer;
+ DBG("_DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X\n",
+ DataSize, Data[0], DataSize > 1 ? Data[1] : 0);
+
+ if (Level < 2 && Data[0] != AML_PACKAGE_OP)
+ continue;
+
+ if (Level == 2 && Data[0] == AML_STRING_PREFIX) {
+ Status = AcpiTableProtocol->GetOption(CurrentHandle, 1, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ DBG(" _DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X\n",
+ DataSize, Data[0], DataSize > 1 ? Data[1] : 0);
+
+ Data = Buffer;
+ if (DataType != EFI_ACPI_DATA_TYPE_STRING
+ || AsciiStrCmp((CHAR8 *) Data, ACPI_ETH_MAC_KEY) != 0)
+ continue;
+
+ DBG("_DSD Key Type %d. Found MAC address key\n", DataType);
+
+ //
+ // We found the node.
+ //
+ *Found = TRUE;
+ continue;
+ }
+
+ if (Level == 3 && *Found) {
+
+ //Update the MAC
+ Status = GetEnvMac(MacNextID, MACBuffer);
+ if (EFI_ERROR(Status))
+ break;
+
+ for (Count = 0; Count < 6; Count++) {
+ Status = AcpiTableProtocol->GetOption(CurrentHandle, 1, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ Data = Buffer;
+ DBG(" _DSD Child Subnode Store Op Code 0x%02X 0x%02X %02X DataType 0x%X\n",
+ DataSize, Data[0], DataSize > 1 ? Data[1] : 0, DataType);
+
+ if (DataType != EFI_ACPI_DATA_TYPE_UINT)
+ break;
+
+ // only need one byte.
+ // FIXME: Assume the CPU is little endian
+ Status = AcpiTableProtocol->SetOption(CurrentHandle, 1, (VOID *)&MACBuffer[Count], sizeof(UINT8));
+ if (EFI_ERROR(Status))
+ break;
+ Status = AcpiTableProtocol->GetChild(ChildHandle, &CurrentHandle);
+ if (EFI_ERROR(Status) || CurrentHandle == NULL)
+ break;
+ }
+ break;
+ }
+
+ if (Level > 3)
+ break;
+
+ //Search next package
+ AcpiTableProtocol->Open((VOID *) Buffer, &NextHandle);
+ Status = _SearchReplacePackageMACAddress(AcpiTableProtocol, NextHandle, Level + 1, Found, MacNextID);
+ AcpiTableProtocol->Close(NextHandle);
+ if (!EFI_ERROR(Status))
+ break;
+ }
+
+ return Status;
+}
+
+EFI_STATUS SearchReplacePackageMACAddress(
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ IN EFI_ACPI_HANDLE ChildHandle,
+ IN UINTN MacNextID)
+{
+ BOOLEAN Found = FALSE;
+ UINTN Level = 0;
+
+ return _SearchReplacePackageMACAddress(AcpiTableProtocol, ChildHandle, Level, &Found, MacNextID);
+}
+
+EFI_STATUS
+GetEthID (
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ EFI_ACPI_HANDLE ChildHandle,
+ UINTN *EthID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ CHAR8 Data[5];
+ CONST VOID *Buffer;
+ UINTN DataSize;
+
+ // Get NameString ETHx
+ Status = AcpiTableProtocol->GetOption (ChildHandle, 1, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] Get NameString failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ CopyMem (Data, Buffer, 4);
+ DBG("Size %p Data %02x %02x %02x %02x\n", DataSize, Data[0], Data[1], Data[2], Data[3]);
+
+ Data[4] = '\0';
+ if (DataSize != 4 ||
+ AsciiStrnCmp ("ETH", Data, 3) != 0 ||
+ Data[3] > '9' || Data[3] < '0') {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] The NameString %a is not ETHn\n", __FUNCTION__, __LINE__, Data));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *EthID = Data[3] - '0';
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS ProcessDSDTDevice (
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ EFI_ACPI_HANDLE ChildHandle)
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ CONST UINT8 *Data;
+ CONST VOID *Buffer;
+ UINTN DataSize;
+ EFI_ACPI_HANDLE DevHandle;
+ INTN Found = 0;
+ UINTN MacNextID;
+
+ Status = AcpiTableProtocol->GetOption(ChildHandle, 0, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ return EFI_SUCCESS;
+
+ Data = Buffer;
+ //
+ // Skip all non-device type
+ //
+ if (DataSize != 2 || Data[0] != AML_EXT_OP || Data[1] != AML_EXT_DEVICE_OP)
+ return EFI_SUCCESS;
+
+ //
+ // Walk the device type node
+ //
+ for (DevHandle = NULL; ; ) {
+ Status = AcpiTableProtocol->GetChild(ChildHandle, &DevHandle);
+ if (EFI_ERROR(Status) || DevHandle == NULL)
+ break;
+
+ //
+ // Search for _HID with Ethernet ID
+ //
+ Status = AcpiTableProtocol->GetOption(DevHandle, 0, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ Data = Buffer;
+ DBG("Data Type 0x%02X %02X\n", Data[0], DataSize > 1 ? Data[1] : 0);
+ if (DataSize == 1 && Data[0] == AML_NAME_OP) {
+ Status = AcpiTableProtocol->GetOption(DevHandle, 1, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ Data = Buffer;
+ if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) {
+ if (AsciiStrnCmp((CHAR8 *) Data, "_HID", 4) == 0) {
+ EFI_ACPI_HANDLE ValueHandle;
+
+ Status = AcpiTableProtocol->GetOption(DevHandle, 2, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ if (DataType != EFI_ACPI_DATA_TYPE_CHILD)
+ continue;
+
+ AcpiTableProtocol->Open((VOID *) Buffer, &ValueHandle);
+ Status = AcpiTableProtocol->GetOption(ValueHandle, 1, &DataType, &Buffer, &DataSize);
+
+ Data = Buffer;
+ DBG("[%a:%d] - _HID = %a\n", __FUNCTION__, __LINE__, Data);
+
+ if (EFI_ERROR(Status) ||
+ DataType != EFI_ACPI_DATA_TYPE_STRING ||
+ ((AsciiStrCmp((CHAR8 *) Data, D02_ACPI_ETH_ID) != 0) &&
+ (AsciiStrCmp((CHAR8 *) Data, D03_ACPI_ETH_ID) != 0))) {
+ AcpiTableProtocol->Close(ValueHandle);
+ Found = 0;
+ continue;
+ }
+
+ DBG("Found Ethernet device\n");
+ AcpiTableProtocol->Close(ValueHandle);
+ Status = GetEthID (AcpiTableProtocol, ChildHandle, &MacNextID);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ Found = 1;
+ } else if (Found == 1 && AsciiStrnCmp((CHAR8 *) Data, "_DSD", 4) == 0) {
+ //
+ // Patch MAC address for open source kernel
+ //
+ EFI_ACPI_HANDLE PkgHandle;
+ Status = AcpiTableProtocol->GetOption(DevHandle, 2, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status))
+ break;
+
+ if (DataType != EFI_ACPI_DATA_TYPE_CHILD)
+ continue;
+
+ //
+ // Open package data
+ //
+ AcpiTableProtocol->Open((VOID *) Buffer, &PkgHandle);
+ Status = AcpiTableProtocol->GetOption(PkgHandle, 0, &DataType, &Buffer, &DataSize);
+
+ Data = Buffer;
+ DBG("_DSD Subnode Store Op Code 0x%02X %02X\n",
+ Data[0], DataSize > 1 ? Data[1] : 0);
+
+ //
+ // Walk the _DSD node
+ //
+ if (DataSize == 1 && Data[0] == AML_PACKAGE_OP)
+ Status = SearchReplacePackageMACAddress(AcpiTableProtocol, PkgHandle, MacNextID);
+
+ AcpiTableProtocol->Close(PkgHandle);
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+BOOLEAN
+IsSbScope (
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ EFI_ACPI_HANDLE ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DATA_TYPE DataType;
+ CONST UINT8 *Data;
+ CONST VOID *Buffer;
+ UINTN DataSize;
+
+ Status = AcpiTableProtocol->GetOption (ChildHandle, 0, &DataType, &Buffer, &DataSize);
+ if (EFI_ERROR(Status)) return FALSE;
+
+ Data = Buffer;
+ if (DataSize != 1 || Data[0] != AML_SCOPE_OP) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS ProcessDSDTChild(
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ EFI_ACPI_HANDLE ChildHandle)
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE DevHandle;
+
+ // Check Scope(_SB) at first
+ if (!IsSbScope (AcpiTableProtocol, ChildHandle)) {
+ return ProcessDSDTDevice (AcpiTableProtocol, ChildHandle);
+ }
+
+ for (DevHandle = NULL; ; ) {
+ Status = AcpiTableProtocol->GetChild (ChildHandle, &DevHandle);
+ if (EFI_ERROR(Status) || DevHandle == NULL) {
+ break;
+ }
+
+ ProcessDSDTDevice (AcpiTableProtocol, DevHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+static EFI_STATUS ProcessDSDT(
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol,
+ EFI_ACPI_HANDLE TableHandle)
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE ChildHandle;
+ //
+ // Parse table for device type
+ DBG ("[%a:%d] - TableHandle=%p\n", __FUNCTION__, __LINE__, TableHandle);
+ for (ChildHandle = NULL; ; ) {
+ Status = AcpiTableProtocol->GetChild(TableHandle, &ChildHandle);
+ DBG ("[%a:%d] - Child=%p, %r\n", __FUNCTION__, __LINE__, ChildHandle, Status);
+ if (EFI_ERROR(Status))
+ break;
+ if (ChildHandle == NULL)
+ break;
+
+ ProcessDSDTChild(AcpiTableProtocol, ChildHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+AcpiCheckSum (
+ IN OUT EFI_ACPI_SDT_HEADER *Table
+ )
+{
+ UINTN ChecksumOffset;
+ UINT8 *Buffer;
+
+ ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
+ Buffer = (UINT8 *)Table;
+
+ //
+ // set checksum to 0 first
+ //
+ Buffer[ChecksumOffset] = 0;
+
+ //
+ // Update checksum value
+ //
+ Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Table->Length);
+}
+
+EFI_STATUS EthMacInit(void)
+{
+ EFI_STATUS Status;
+ EFI_ACPI_SDT_PROTOCOL *AcpiTableProtocol;
+ EFI_ACPI_SDT_HEADER *Table;
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ UINTN TableKey;
+ EFI_ACPI_HANDLE TableHandle;
+ UINTN i;
+
+ DEBUG ((EFI_D_ERROR, "Updating Ethernet MAC in ACPI DSDT...\n"));
+
+ //
+ // Find the AcpiTable protocol
+ Status = gBS->LocateProtocol(&gEfiAcpiSdtProtocolGuid, NULL, (VOID**) &AcpiTableProtocol);
+ if (EFI_ERROR(Status)) {
+ DBG("Unable to locate ACPI table protocol\n");
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Search for DSDT Table
+ for (i = 0; i < EFI_ACPI_MAX_NUM_TABLES; i++) {
+ Status = AcpiTableProtocol->GetAcpiTable(i, &Table, &TableVersion, &TableKey);
+ if (EFI_ERROR(Status))
+ break;
+ if (Table->Signature != DSDT_SIGNATURE)
+ continue;
+
+ Status = AcpiTableProtocol->OpenSdt(TableKey, &TableHandle);
+ if (EFI_ERROR(Status))
+ break;
+
+ ProcessDSDT(AcpiTableProtocol, TableHandle);
+
+ AcpiTableProtocol->Close(TableHandle);
+ AcpiCheckSum (Table);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h
new file mode 100644
index 0000000000..bf4cbb1a53
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/AcpiPlatformDxe/EthMac.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+ * Copyright (c) 2015, Linaro Limited. All rights reserved.
+ * Author: Loc Ho <lho@apm.com>
+ *
+ * This program and the accompanying materials
+ *are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ */
+#ifndef _ETH_MAC_H_
+#define _ETH_MAC_H_
+
+EFI_STATUS EthMacInit(VOID);
+
+#endif
+
diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c
new file mode 100644
index 0000000000..91c07338ed
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashBlockIoDxe.c
@@ -0,0 +1,109 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "FlashFvbDxe.h"
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID* Buffer
+)
+{
+ FLASH_INSTANCE* Instance;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+ DEBUG ((EFI_D_INFO, "FlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+ if ( !This->Media->MediaPresent )
+ {
+ Status = EFI_NO_MEDIA;
+ }
+ else if ( This->Media->MediaId != MediaId )
+ {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else
+ {
+ Status = FlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID* Buffer
+)
+{
+ FLASH_INSTANCE* Instance;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+ DEBUG ((EFI_D_INFO, "FlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+ if ( !This->Media->MediaPresent )
+ {
+ Status = EFI_NO_MEDIA;
+ }
+ else if ( This->Media->MediaId != MediaId )
+ {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else if ( This->Media->ReadOnly )
+ {
+ Status = EFI_WRITE_PROTECTED;
+ }
+ else
+ {
+ Status = FlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This
+)
+{
+ // No Flush required for the NOR Flash driver
+ // because cache operations are not permitted.
+
+ // Nothing to do so just return without error
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c
new file mode 100644
index 0000000000..7c6b64c33e
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.c
@@ -0,0 +1,1243 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+* Based on files under ArmPlatformPkg/Drivers/NorFlashDxe/
+**/
+
+#include "FlashFvbDxe.h"
+STATIC EFI_EVENT mFlashFvbVirtualAddrChangeEvent;
+STATIC UINTN mFlashNvStorageVariableBase;
+
+
+//
+// Global variable declarations
+//
+
+FLASH_DESCRIPTION mFlashDevices[FLASH_DEVICE_COUNT] =
+{
+ {
+ // UEFI Variable Services non-volatile storage
+ 0xa4000000,
+ FixedPcdGet32(PcdFlashNvStorageVariableBase),
+ 0x20000,
+ SIZE_64KB,
+ {0xCC2CBF29, 0x1498, 0x4CDD, {0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09}}
+ }
+
+};
+
+FLASH_INSTANCE** mFlashInstances;
+
+FLASH_INSTANCE mFlashInstanceTemplate =
+{
+ FLASH_SIGNATURE, // Signature
+ NULL, // Handle ... NEED TO BE FILLED
+
+ FALSE, // Initialized
+ NULL, // Initialize
+
+ 0, // DeviceBaseAddress ... NEED TO BE FILLED
+ 0, // RegionBaseAddress ... NEED TO BE FILLED
+ 0, // Size ... NEED TO BE FILLED
+ 0, // StartLba
+
+ {
+ EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
+ NULL, // Media ... NEED TO BE FILLED
+ NULL, //NorFlashBlockIoReset
+ FlashBlockIoReadBlocks,
+ FlashBlockIoWriteBlocks,
+ FlashBlockIoFlushBlocks
+ }, // BlockIoProtocol
+
+ {
+ 0, // MediaId ... NEED TO BE FILLED
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching;
+ SIZE_64KB, // BlockSize ... NEED TO BE FILLED
+ 4, // IoAlign
+ 0, // LastBlock ... NEED TO BE FILLED
+ 0, // LowestAlignedLba
+ 1, // LogicalBlocksPerPhysicalBlock
+ }, //Media;
+
+ FALSE, // SupportFvb ... NEED TO BE FILLED
+ {
+ FvbGetAttributes,
+ FvbSetAttributes,
+ FvbGetPhysicalAddress,
+ FvbGetBlockSize,
+ FvbRead,
+ FvbWrite,
+ FvbEraseBlocks,
+ NULL, //ParentHandle
+ }, // FvbProtoccol;
+
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {(UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)},
+ },
+ { 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}, // GUID ... NEED TO BE FILLED
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0}
+ }
+ } // DevicePath
+};
+
+HISI_SPI_FLASH_PROTOCOL* mFlash;
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN FLASH_INSTANCE* Instance
+)
+{
+ EFI_STATUS Status;
+ VOID* Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER* FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER* VariableStoreHeader;
+
+ if (!Instance->Initialized && Instance->Initialize)
+ {
+ Instance->Initialize (Instance);
+ }
+
+ HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool(HeadersLength);
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase));
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase));
+
+ // Check if the size of the area is at least one block size
+ ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT((UINT32)PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
+ ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
+ ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + (UINTN)FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
+ VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+
+ FreePool (Headers);
+ return Status;
+}
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN FLASH_INSTANCE* Instance
+)
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER* FwVolHeader;
+ VARIABLE_STORE_HEADER* VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress;
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE )
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0)
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n", Checksum));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + (UINTN)FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if ( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE )
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength)
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The FvbGetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ OUT EFI_FVB_ATTRIBUTES_2* Attributes
+)
+{
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ FLASH_INSTANCE* Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
+
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+
+ );
+
+ // Check if it is write protected
+ if (Instance->Media.ReadOnly != TRUE)
+ {
+
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The FvbSetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
+ that contains the desired firmware volume settings.
+ On successful return, it contains the new settings of
+ the firmware volume.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
+ as declared in the firmware volume header.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN OUT EFI_FVB_ATTRIBUTES_2* Attributes
+)
+{
+ DEBUG ((EFI_D_ERROR, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ OUT EFI_PHYSICAL_ADDRESS* Address
+)
+{
+
+ if(NULL == Address)
+ {
+ return EFI_UNSUPPORTED;
+ };
+
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ OUT UINTN* BlockSize,
+ OUT UINTN* NumberOfBlocks
+)
+{
+ EFI_STATUS Status;
+ FLASH_INSTANCE* Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ if (Lba > Instance->Media.LastBlock)
+ {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else
+ {
+ // This is easy because in this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN) Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
+
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+FvbReset(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+)
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be used
+ to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
+ in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN* NumBytes,
+ IN OUT UINT8* Buffer
+)
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ FLASH_INSTANCE* Instance;
+
+ UINTN StartAddress;
+ UINTN ReadAddress;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ if (!Instance->Initialized && Instance->Initialize)
+ {
+ if (EfiAtRuntime ()) {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__));
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance->Initialize(Instance);
+ }
+
+ Status = EFI_SUCCESS;
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL] ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", __FUNCTION__, __LINE__, Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ if (*NumBytes == 0)
+ {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+ Lba,
+ BlockSize
+ );
+ ReadAddress = StartAddress - Instance->DeviceBaseAddress + Offset;
+
+ Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, *NumBytes);
+ if (EFI_SUCCESS != Status)
+ {
+ // Return one of the pre-approved error statuses
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+
+ return Status;
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
+
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN* NumBytes,
+ IN UINT8* Buffer
+)
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ FLASH_INSTANCE* Instance;
+ UINTN BlockAddress;
+ UINTN WriteAddress;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+ if (NULL == Instance)
+ {
+ return EFI_INVALID_PARAMETER;
+
+ }
+
+ if (!Instance->Initialized && Instance->Initialize)
+ {
+ if (EfiAtRuntime ()) {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__));
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance->Initialize(Instance);
+ }
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not write: Device is in WriteDisabled state.\n"));
+ // It is in WriteDisabled state, return an error right away
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // The write must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ( ( Offset >= BlockSize ) ||
+ ( *NumBytes > BlockSize ) ||
+ ( (Offset + *NumBytes) > BlockSize ) )
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to write
+ if (*NumBytes == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
+ WriteAddress = BlockAddress - Instance->DeviceBaseAddress + Offset;
+
+ Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, *NumBytes);
+ if (EFI_SUCCESS != Status)
+ {
+ DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
+ return Status;
+ }
+
+ return Status;
+
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to erase.
+
+ The list is terminated with an EFI_LBA_LIST_TERMINATOR.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
+ The firmware device may have been partially erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
+ not exist in the firmware volume.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ ...
+)
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ UINTN BlockAddress; // Physical address of Lba to erase
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ FLASH_INSTANCE* Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE)
+ {
+ // Firmware volume is in WriteDisabled state
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+ VA_START (Args, This);
+ do
+ {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR)
+ {
+ //Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // All blocks must be within range
+ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock))
+ {
+ VA_END (Args);
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ }
+ while (TRUE);
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do
+ {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR)
+ {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0)
+ {
+
+ // Get the physical address of Lba to erase
+ BlockAddress = GET_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+
+ Status = FlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR(Status))
+ {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ }
+ while (TRUE);
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ IN FLASH_INSTANCE* Instance
+)
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+
+ Instance->Initialized = TRUE;
+ mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
+
+ // Set the index of the first LBA for the FVB
+ Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
+
+ // Determine if there is a valid header at the beginning of the Flash
+ Status = ValidateFvHeader (Instance);
+ if (EFI_ERROR(Status))
+ {
+ // There is no valid header, so time to install one.
+ // Erase all the Flash that is reserved for variable storage
+ FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + (UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR(Status))
+ {
+ return Status;
+ }
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR(Status))
+ {
+ return Status;
+ }
+ }
+ return Status;
+}
+
+
+EFI_STATUS
+FlashPlatformGetDevices (
+ OUT FLASH_DESCRIPTION** FlashDevices,
+ OUT UINT32* Count
+)
+{
+ if ((FlashDevices == NULL) || (Count == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *FlashDevices = mFlashDevices;
+ *Count = FLASH_DEVICE_COUNT;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FlashCreateInstance (
+ IN UINTN FlashDeviceBase,
+ IN UINTN FlashRegionBase,
+ IN UINTN FlashSize,
+ IN UINT32 MediaId,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ IN CONST GUID* FlashGuid,
+ OUT FLASH_INSTANCE** FlashInstance
+)
+{
+ EFI_STATUS Status;
+ FLASH_INSTANCE* Instance;
+
+ if (FlashInstance == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = AllocateRuntimeCopyPool (sizeof(FLASH_INSTANCE), &mFlashInstanceTemplate);
+ if (Instance == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance->DeviceBaseAddress = FlashDeviceBase;
+ Instance->RegionBaseAddress = FlashRegionBase;
+ Instance->Size = FlashSize;
+
+ Instance->BlockIoProtocol.Media = &Instance->Media;
+ Instance->BlockIoProtocol.Reset = FvbReset;
+ Instance->Media.MediaId = MediaId;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = (FlashSize / BlockSize) - 1;
+
+ CopyGuid (&Instance->DevicePath.Vendor.Guid, FlashGuid);
+
+ if (SupportFvb)
+ {
+ Instance->SupportFvb = TRUE;
+ Instance->Initialize = FvbInitialize;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
+ NULL
+ );
+
+ if (EFI_ERROR(Status))
+ {
+ FreePool(Instance);
+ return Status;
+ }
+ }
+ else
+ {
+ Instance->Initialized = TRUE;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ NULL
+ );
+ if (EFI_ERROR(Status))
+ {
+ FreePool(Instance);
+ return Status;
+ }
+ }
+
+ *FlashInstance = Instance;
+ return Status;
+}
+
+EFI_STATUS
+FlashUnlockSingleBlockIfNecessary (
+ IN FLASH_INSTANCE* Instance,
+ IN UINTN BlockAddress
+)
+{
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FlashEraseSingleBlock (
+ IN FLASH_INSTANCE* Instance,
+ IN UINTN BlockAddress
+)
+{
+ EFI_STATUS Status;
+ UINTN EraseAddress;
+
+ Status = EFI_SUCCESS;
+ EraseAddress = BlockAddress - Instance->DeviceBaseAddress;
+
+ Status = mFlash->Erase(mFlash, (UINT32)EraseAddress, Instance->Media.BlockSize);
+ if (EFI_SUCCESS != Status)
+ {
+ DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+EFI_STATUS
+FlashUnlockAndEraseSingleBlock (
+ IN FLASH_INSTANCE* Instance,
+ IN UINTN BlockAddress
+)
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Index = 0;
+ // The block erase might fail a first time (SW bug ?). Retry it ...
+ do
+ {
+ // Unlock the block if we have to
+ Status = FlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ if (!EFI_ERROR(Status))
+ {
+ Status = FlashEraseSingleBlock (Instance, BlockAddress);
+ }
+ Index++;
+ }
+ while ((Index < FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+ if (Index == FLASH_ERASE_RETRY)
+ {
+ DEBUG((EFI_D_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FlashWriteBlocks (
+ IN FLASH_INSTANCE* Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID* Buffer
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BlockAddress;
+ UINT32 NumBlocks;
+ UINTN WriteAddress;
+
+ // The buffer must be valid
+ if (Buffer == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Instance->Media.ReadOnly == TRUE)
+ {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ // We must have some bytes to read
+ if (BufferSizeInBytes == 0)
+ {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0)
+ {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]ERROR - Write will exceed last block.\n", __FUNCTION__, __LINE__ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, Instance->Media.BlockSize);
+
+ WriteAddress = BlockAddress - Instance->DeviceBaseAddress;
+
+ Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, BufferSizeInBytes);
+ if (EFI_SUCCESS != Status)
+ {
+ DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
+ return Status;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FlashReadBlocks (
+ IN FLASH_INSTANCE* Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID* Buffer
+)
+{
+ UINT32 NumBlocks;
+ UINTN StartAddress;
+ UINTN ReadAddress;
+ EFI_STATUS Status;
+
+ // The buffer must be valid
+ if (Buffer == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // We must have some bytes to read
+ if (BufferSizeInBytes == 0)
+ {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0)
+ {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1))
+ {
+ DEBUG((EFI_D_ERROR, "FlashReadBlocks: ERROR - Read will exceed last block\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+
+ ReadAddress = StartAddress - Instance->DeviceBaseAddress;
+
+ Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, BufferSizeInBytes);
+ if (EFI_SUCCESS != Status)
+ {
+ DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+FlashFvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID**)&mFlash);
+ EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+FlashFvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE* SystemTable
+)
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ FLASH_DESCRIPTION* FlashDevices;
+ UINT32 FlashDeviceCount;
+ BOOLEAN ContainVariableStorage;
+
+
+ Status = FlashPlatformGetDevices (&FlashDevices, &FlashDeviceCount);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to get Flash devices\n", __FUNCTION__, __LINE__));
+ return Status;
+ }
+
+ mFlashInstances = AllocatePool ((UINT32)(sizeof(FLASH_INSTANCE*) * FlashDeviceCount));
+
+ Status = gBS->LocateProtocol (&gHisiSpiFlashProtocolGuid, NULL, (VOID*) &mFlash);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status=%r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ for (Index = 0; Index < FlashDeviceCount; Index++)
+ {
+ // Check if this Flash device contain the variable storage region
+ ContainVariableStorage =
+ (FlashDevices[Index].RegionBaseAddress <= (UINT32)PcdGet32 (PcdFlashNvStorageVariableBase)) &&
+ ((UINT32)(PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize)) <= FlashDevices[Index].RegionBaseAddress + FlashDevices[Index].Size);
+
+ Status = FlashCreateInstance (
+ FlashDevices[Index].DeviceBaseAddress,
+ FlashDevices[Index].RegionBaseAddress,
+ FlashDevices[Index].Size,
+ Index,
+ FlashDevices[Index].BlockSize,
+ ContainVariableStorage,
+ &FlashDevices[Index].Guid,
+ &mFlashInstances[Index]
+ );
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to create instance for Flash[%d]\n", __FUNCTION__, __LINE__, Index));
+ }
+ }
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FlashFvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFlashFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h
new file mode 100644
index 0000000000..76385b6b65
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.h
@@ -0,0 +1,228 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#ifndef __FLASH_FVB_DXE_H__
+#define __FLASH_FVB_DXE_H__
+
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Library/DebugLib.h>
+
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/HisiSpiFlashProtocol.h>
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Guid/VariableFormat.h>
+#include <Guid/SystemNvDataGuid.h>
+
+
+#define FLASH_ERASE_RETRY 10
+#define FLASH_DEVICE_COUNT 1
+
+// Device access macros
+// These are necessary because we use 2 x 16bit parts to make up 32bit data
+typedef struct
+{
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
+ UINTN RegionBaseAddress; // Start address of one single region
+ UINTN Size;
+ UINTN BlockSize;
+ EFI_GUID Guid;
+} FLASH_DESCRIPTION;
+
+#define GET_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+#define FLASH_SIGNATURE SIGNATURE_32('s', 'p', 'i', '0')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, FLASH_INSTANCE, FvbProtocol, FLASH_SIGNATURE)
+#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, FLASH_INSTANCE, BlockIoProtocol, FLASH_SIGNATURE)
+
+typedef struct _FLASH_INSTANCE FLASH_INSTANCE;
+
+typedef EFI_STATUS (*FLASH_INITIALIZE) (FLASH_INSTANCE* Instance);
+
+typedef struct
+{
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FLASH_DEVICE_PATH;
+
+struct _FLASH_INSTANCE
+{
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ BOOLEAN Initialized;
+ FLASH_INITIALIZE Initialize;
+
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+
+ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
+ EFI_BLOCK_IO_MEDIA Media;
+
+ BOOLEAN SupportFvb;
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+
+ FLASH_DEVICE_PATH DevicePath;
+};
+
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID* Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID* Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+FlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL* This
+);
+
+
+//
+// FvbHw.c
+//
+
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ IN FLASH_INSTANCE* Instance
+);
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ OUT EFI_FVB_ATTRIBUTES_2* Attributes
+);
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN OUT EFI_FVB_ATTRIBUTES_2* Attributes
+);
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ OUT EFI_PHYSICAL_ADDRESS* Address
+);
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ OUT UINTN* BlockSize,
+ OUT UINTN* NumberOfBlocks
+);
+
+EFI_STATUS
+EFIAPI
+FvbRead(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN* NumBytes,
+ IN OUT UINT8* Buffer
+);
+
+EFI_STATUS
+EFIAPI
+FvbWrite(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN* NumBytes,
+ IN UINT8* Buffer
+);
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
+ ...
+);
+
+//
+// FlashFvbDxe.c
+//
+
+EFI_STATUS
+FlashUnlockAndEraseSingleBlock (
+ IN FLASH_INSTANCE* Instance,
+ IN UINTN BlockAddress
+);
+
+EFI_STATUS
+FlashWriteBlocks (
+ IN FLASH_INSTANCE* Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID* Buffer
+);
+
+EFI_STATUS
+FlashReadBlocks (
+ IN FLASH_INSTANCE* Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID* Buffer
+);
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf
new file mode 100644
index 0000000000..09ec7ce08b
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/FlashFvbDxe/FlashFvbDxe.inf
@@ -0,0 +1,69 @@
+#/** @file
+#
+# Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FlashFvbDxe
+ FILE_GUID = 93E34C7E-B50E-11DF-9223-2443DFD72085
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FlashFvbInitialize
+
+[Sources.common]
+ FlashFvbDxe.c
+ FlashBlockIoDxe.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ BaseLib
+ DebugLib
+ HobLib
+ UefiLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gHisiSpiFlashProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+ gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
+
+[Depex]
+ gHisiSpiFlashProtocolGuid
+
+[BuildOptions]
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..c8b56e1bd1
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,269 @@
+/** @file
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Acpi.h>
+#include "UpdateAcpiTable.h"
+
+/**
+ 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.
+
+ @param Instance Return pointer to the first instance of the protocol
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND The protocol could not be located.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+ OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ 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 (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID**) &FvInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // See if it has the ACPI storage file
+ //
+ Status = FvInstance->ReadFile (
+ FvInstance,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (Status == EFI_SUCCESS) {
+ *Instance = FvInstance;
+ 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 calculates and updates an UINT8 checksum.
+
+ @param Buffer Pointer to buffer to checksum
+ @param Size Number of bytes to checksum
+
+**/
+VOID
+AcpiPlatformChecksum (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ UINTN ChecksumOffset;
+
+ ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
+
+ //
+ // Set checksum to 0 first
+ //
+ Buffer[ChecksumOffset] = 0;
+
+ //
+ // Update checksum value
+ //
+ Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size);
+}
+
+
+/**
+ Entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+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 TableSize;
+ UINTN Size;
+ EFI_STATUS TableStatus;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+
+ Instance = 0;
+ CurrentTable = NULL;
+ TableHandle = 0;
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateFvInstanceWithTables (&FwVol);
+ 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)) {
+ //
+ // Add the table
+ //
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER*) (CurrentTable);
+ //Update specfic Acpi Table
+ //If the Table is updated failed, doesn't install it,
+ //go to find next section.
+ TableStatus = UpdateAcpiTable(TableHeader);
+ if (TableStatus == EFI_SUCCESS) {
+ TableHandle = 0;
+
+ TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
+ ASSERT (Size >= TableSize);
+
+ //
+ // Checksum ACPI table
+ //
+ AcpiPlatformChecksum ((UINT8*)CurrentTable, TableSize);
+
+ //
+ // Install ACPI table
+ //
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ TableSize,
+ &TableHandle
+ );
+ }
+ //
+ // Free memory allocated by ReadSection
+ //
+ gBS->FreePool (CurrentTable);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni
new file mode 100644
index 0000000000..1275549bd0
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatform.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Sample ACPI Platform Driver
+//
+// Sample ACPI Platform Driver
+//
+// Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Sample ACPI Platform Driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Sample ACPI Platform Driver"
+
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..e268a56bbd
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,62 @@
+## @file
+# Sample ACPI Platform Driver
+#
+# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ MODULE_UNI_FILE = AcpiPlatform.uni
+ FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c
+ 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 IPF EBC
+#
+
+[Sources]
+ AcpiPlatform.c
+ UpdateAcpiTable.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ DxeServicesLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+
+[Guids]
+ gHisiEfiMemoryMapGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile ## CONSUMES
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ AcpiPlatformExtra.uni
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni
new file mode 100644
index 0000000000..4c21968f7a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// AcpiPlatform Localized Strings and Content
+//
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"ACPI Platform Sample DXE Driver"
+
+
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c
new file mode 100644
index 0000000000..7d06fccc2b
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.c
@@ -0,0 +1,137 @@
+/** @file
+ Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <PlatformArch.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/AcpiNextLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/HwMemInitLib.h>
+#include <Library/OemMiscLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#define CORE_NUM_PER_SOCKET 32
+#define NODE_IN_SOCKET 2
+#define CORECOUNT(X) ((X) * CORE_NUM_PER_SOCKET)
+
+STATIC
+VOID
+RemoveUnusedMemoryNode (
+ IN OUT EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *Table,
+ IN UINTN MemoryNodeNum
+)
+{
+ UINTN CurrPtr, NewPtr;
+
+ if (MemoryNodeNum >= EFI_ACPI_MEMORY_AFFINITY_STRUCTURE_COUNT) {
+ return;
+ }
+
+ CurrPtr = (UINTN) &(Table->Memory[EFI_ACPI_MEMORY_AFFINITY_STRUCTURE_COUNT]);
+ NewPtr = (UINTN) &(Table->Memory[MemoryNodeNum]);
+
+ CopyMem ((VOID *)NewPtr, (VOID *)CurrPtr, (UINTN)Table + Table->Header.Header.Length - CurrPtr);
+
+ Table->Header.Header.Length -= CurrPtr - NewPtr;
+
+ return;
+}
+
+STATIC
+EFI_STATUS
+UpdateSrat (
+ IN OUT EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *Table
+ )
+{
+ UINT8 Skt = 0;
+ UINTN Index = 0;
+ VOID *HobList;
+ GBL_DATA *Gbl_Data;
+ UINTN Base;
+ UINTN Size;
+ UINT8 NodeId;
+ UINT32 ScclInterleaveEn;
+ UINTN MemoryNode = 0;
+
+ DEBUG((DEBUG_INFO, "SRAT: Updating SRAT memory information.\n"));
+
+ HobList = GetHobList();
+ if (HobList == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ Gbl_Data = (GBL_DATA*)GetNextGuidHob(&gHisiEfiMemoryMapGuid, HobList);
+ if (Gbl_Data == NULL) {
+ DEBUG((DEBUG_ERROR, "Get next Guid HOb fail.\n"));
+ return EFI_NOT_FOUND;
+ }
+ Gbl_Data = GET_GUID_HOB_DATA(Gbl_Data);
+ for(Skt = 0; Skt < MAX_SOCKET; Skt++) {
+ for(Index = 0; Index < MAX_NUM_PER_TYPE; Index++) {
+ NodeId = Gbl_Data->NumaInfo[Skt][Index].NodeId;
+ Base = Gbl_Data->NumaInfo[Skt][Index].Base;
+ Size = Gbl_Data->NumaInfo[Skt][Index].Length;
+ DEBUG((DEBUG_INFO, "Skt %d Index %d: NodeId = %d, Base = 0x%lx, Size = 0x%lx\n", Skt, Index, NodeId, Base, Size));
+ if (Size > 0) {
+ Table->Memory[MemoryNode].ProximityDomain = NodeId;
+ Table->Memory[MemoryNode].AddressBaseLow = Base;
+ Table->Memory[MemoryNode].AddressBaseHigh = Base >> 32;
+ Table->Memory[MemoryNode].LengthLow = Size;
+ Table->Memory[MemoryNode].LengthHigh = Size >> 32;
+ MemoryNode = MemoryNode + 1;
+ }
+ }
+ ScclInterleaveEn = Gbl_Data->NumaInfo[Skt][0].ScclInterleaveEn;
+ DEBUG((DEBUG_INFO, "ScclInterleaveEn = %d\n", ScclInterleaveEn));
+ //update gicc structure
+ if (ScclInterleaveEn != 0) {
+ DEBUG((DEBUG_INFO, "SRAT: Updating SRAT Gicc information.\n"));
+ for (Index = CORECOUNT (Skt); Index < CORECOUNT (Skt + 1); Index++) {
+ Table->Gicc[Index].ProximityDomain = Skt * NODE_IN_SOCKET;
+ }
+ }
+ }
+
+ //remove invalid memory node
+ RemoveUnusedMemoryNode (Table, MemoryNode);
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+UpdateSlit (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateAcpiTable (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ switch (TableHeader->Signature) {
+
+ case EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE:
+ Status = UpdateSrat ((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) TableHeader);
+ break;
+
+ case EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
+ Status = UpdateSlit (TableHeader);
+ break;
+ }
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h
new file mode 100644
index 0000000000..45b3729b6a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/UpdateAcpiTable.h
@@ -0,0 +1,16 @@
+/** @file
+ Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+EFI_STATUS
+UpdateAcpiTable (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
+);
+
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c
new file mode 100644
index 0000000000..ab3b70caf2
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c
@@ -0,0 +1,162 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#include "NorFlashHw.h"
+
+
+#define COMMAND_TYPE1 0x1
+#define COMMAND_TYPE2 0x2
+#define COMMAND_TYPE3 0x4
+#define COMMAND_TYPE4 0x8
+#define COMMAND_TYPE5 0x10
+
+
+NOR_FLASH_INFO_TABLE gFlashInfo[]=
+{
+
+ {//S29GL512m
+ 0x00010001,
+ 0x227E227E,
+ 0x22232223,
+ 0x22012201,
+ 1,
+ 0x20000000,
+ 0x20000,
+ 0x0010,
+ COMMAND_TYPE1
+ },
+ {//S29GL1g
+ 0x00010001,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 1,
+ 0x40000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {//M29ew512m
+ 0x00890089,
+ 0x227E227E,
+ 0x22232223,
+ 0x22012201,
+ 1,
+ 0x20000000,
+ 0x20000,
+ 0x0010,
+ COMMAND_TYPE1
+ },
+ {//M29EW2g
+ 0x00890089,
+ 0x227E227E,
+ 0x22482248,
+ 0x22012201,
+ 1,
+ 0x80000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {
+ 0x00890089,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 1,
+ 0x10000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {
+ 0x00890089,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 2,
+ 0x10000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ }
+};
+
+
+
+FLASH_COMMAND_RESET gFlashCommandReset[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x00F000F0)
+ }
+
+};
+
+
+FLASH_COMMAND_ID gFlashCommandId[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x0555),
+ (0x00900090),
+ (0x0000),
+
+ (0x0001),
+ (0x000E),
+ (0x000F)
+ }
+};
+
+
+FLASH_COMMAND_WRITE gFlashCommandWrite[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x00250025),
+ (0x00290029)
+ }
+
+};
+
+
+FLASH_COMMAND_ERASE gFlashCommandErase[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x0555),
+ (0x00800080),
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x00300030)
+ }
+
+};
+
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 0000000000..8b8a5d7a3f
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,594 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/NorFlashProtocol.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Protocol/Cpu.h>
+#include "NorFlashHw.h"
+
+
+EFI_STATUS Erase(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT32 Length
+ );
+
+EFI_STATUS Write(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ UINT32 ulLength
+ );
+
+EFI_STATUS Read(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 ulLen
+ );
+
+UNI_NOR_FLASH_PROTOCOL gUniNorFlash = {
+ Erase,
+ Write,
+ Read
+};
+
+
+EFI_STATUS
+EFIAPI Read(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 ulLen
+ )
+{
+ UINT32 index;
+ UINT64 ullAddr;
+ UINT32 ullCnt = 0;
+ UINT32 *puiBuffer32 = NULL;
+ UINT32 *puiDst32 = NULL;
+ UINT8 *pucBuffer8 = NULL;
+ UINT8 *pucDst8 = NULL;
+
+ if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (0 == ulLen)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (NULL == Buffer)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+
+ ullAddr = gIndex.Base + Offset;
+
+ pucBuffer8 = (UINT8 *)Buffer;
+ pucDst8 = (UINT8 *)((UINTN)ullAddr);
+
+
+ if (ulLen < FOUR_BYTE_UNIT)
+ {
+ for(index = 0; index< ulLen; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+ }
+ else
+ {
+
+ ullCnt = Offset % FOUR_BYTE_UNIT;
+ ullCnt = FOUR_BYTE_UNIT - ullCnt;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+
+ ulLen -= ullCnt;
+
+ puiBuffer32 = (UINT32 *)pucBuffer8;
+ puiDst32 = (UINT32 *)pucDst8;
+ ullCnt = ulLen / FOUR_BYTE_UNIT;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *puiBuffer32++ = *puiDst32++;
+ }
+
+ ullCnt = ulLen % FOUR_BYTE_UNIT;
+ pucBuffer8 = (UINT8 *)puiBuffer32;
+ pucDst8 = (UINT8 *)puiDst32;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+static EFI_STATUS WriteAfterErase_Fill(
+ IN const UINT32 Offset,
+ IN const UINT8 *Buffer,
+ IN const UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Loop;
+ UINT32 DataOffset;
+ UINT32 NewOffset;
+ UINT8 *NewDataUnit;
+
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+ if ((Offset % FlashUnitLength + Length) > FlashUnitLength)
+ {
+ DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_UNSUPPORTED;
+ }
+
+
+ Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+
+ NewOffset = Offset - (Offset % FlashUnitLength);
+
+ gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength);
+
+ DataOffset = Offset % FlashUnitLength;
+ for (Loop = 0; Loop < Length; Loop ++)
+ {
+ NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop];
+ }
+
+ Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ (void)gBS->FreePool((VOID *)NewDataUnit);
+ return Status;
+}
+
+
+static EFI_STATUS WriteAfterErase_Final(
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Loop;
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+ if (0 != (Offset % FlashUnitLength))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength));
+ return EFI_UNSUPPORTED;
+ }
+
+
+ Loop = Length / FlashUnitLength;
+ while (Loop --)
+ {
+ Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status));
+ return EFI_DEVICE_ERROR;
+ }
+ Offset += FlashUnitLength;
+ Buffer += FlashUnitLength;
+ }
+
+
+ Length = Length % FlashUnitLength;
+ if (Length)
+ {
+ Status = WriteAfterErase_Fill(Offset, Buffer, Length);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteAfterErase(
+ UINT32 TempBase,
+ UINT32 Offset,
+ UINT8 *Buffer,
+ UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ if (Offset % FlashUnitLength)
+ {
+ UINT32 TempLength;
+
+
+ TempLength = FlashUnitLength - (Offset % FlashUnitLength);
+ if (TempLength > Length)
+ {
+ TempLength = Length;
+ }
+ Status = WriteAfterErase_Fill(Offset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ Offset += TempLength;
+ Length -= TempLength;
+ Buffer += TempLength;
+
+ //Desc:if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ gIndex.Base = TempBase;
+ Offset = 0;
+ }
+ }
+
+
+ Status = WriteAfterErase_Final(Offset, Buffer, Length);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FlashSectorErase(
+ UINT32 TempBase,
+ UINT32 Offset,
+ UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SectorOffset;
+ UINT8 *StaticBuffer;
+ UINT8 *Buffer;
+ UINT32 TempOffset;
+ UINT32 TempLength;
+ UINT32 LeftLength;
+
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+ LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+ if (LeftLength < Length)
+ {
+ return EFI_UNSUPPORTED;
+ }
+
+
+ SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+ Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer);
+ if (EFI_ERROR(Status))
+ {
+ return Status;
+ }
+
+ Buffer = StaticBuffer;
+
+ gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset),
+ (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ Status = SectorErase(TempBase, SectorOffset);
+ if (EFI_ERROR(Status))
+ {
+ goto DO;
+ }
+
+
+ TempOffset = SectorOffset;
+ TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum);
+
+ Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ goto DO;
+ }
+
+
+ Buffer = Buffer + TempLength + Length;
+ TempOffset = Offset + Length;
+ TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset;
+
+ Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status));
+ goto DO;
+ }
+
+ (void)gBS->FreePool((VOID *)StaticBuffer);
+ return EFI_SUCCESS;
+
+DO:
+ (void)gBS->FreePool((VOID *)StaticBuffer);
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI Erase(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT32 Length
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 Sectors;
+ UINT32 TempLength;
+ UINT32 TempBase;
+ UINT32 Loop;
+
+
+ if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_ABORTED;
+ }
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
+ TempBase = gIndex.Base;
+
+ //if Offset >= gOneFlashSize,modify base
+ if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ }
+
+ for (Loop = 0; Loop <= Sectors; Loop ++)
+ {
+
+ TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ if (TempLength > Length)
+ {
+ TempLength = Length;
+ }
+
+ Status = FlashSectorErase(TempBase, Offset, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+
+ Offset += TempLength;
+
+ //if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ Offset = 0;
+ }
+ Length -= TempLength;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI Write(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ UINT32 ulLength
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TempLength;
+ UINT32 TempBase;
+ UINT32 Loop;
+ UINT32 Sectors;
+
+ if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (0 == ulLength)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
+ TempBase = gIndex.Base;
+
+ //if Offset >= gOneFlashSize,modify base
+ if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ }
+
+ for (Loop = 0; Loop <= Sectors; Loop ++)
+ {
+
+ TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ if (TempLength > ulLength)
+ {
+ TempLength = ulLength;
+ }
+
+
+ if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength))
+ {
+ Status = FlashSectorErase(TempBase, Offset, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+
+
+ Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+ }
+
+ Offset += TempLength;
+ Buffer += TempLength;
+
+ //if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ Offset = 0;
+ }
+ ulLength -= TempLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID SetFlashAttributeToUncache(VOID)
+{
+ EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status));
+ }
+
+ Status = gCpu->SetMemoryAttributes(
+ gCpu,
+ PcdGet64(PcdNORFlashBase),
+ PcdGet32(PcdNORFlashCachableSize),
+ EFI_MEMORY_UC
+ );
+
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status));
+ }
+
+}
+
+EFI_STATUS
+EFIAPI InitializeFlash (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+
+
+ gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase);
+
+ SetFlashAttributeToUncache();
+ Status = FlashInit(gIndex.Base);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Init Flash Error !\n"));
+ return Status;
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Init Flash OK!\n"));
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gUniNorFlashProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gUniNorFlash);
+ if(EFI_SUCCESS != Status)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status));
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100644
index 0000000000..254e27eeac
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,64 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NorFlashDxe
+ FILE_GUID = E29977F9-20A4-4551-B0EC-BCE246592E73
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFlash
+
+[Sources.common]
+ NorFlashDxe.c
+ NorFlashHw.c
+ NorFlashConfig.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DebugLib
+ BaseLib
+ DebugLib
+ IoLib
+ SerialPortLib
+ ArmLib
+ CacheMaintenanceLib
+ UefiLib
+ PrintLib
+ PcdLib
+
+ DxeServicesTableLib
+[Guids]
+
+[Protocols]
+ gUniNorFlashProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[Pcd]
+ gHisiTokenSpaceGuid.PcdNORFlashBase
+ gHisiTokenSpaceGuid.PcdNORFlashCachableSize
+
+
+[Depex]
+ TRUE
+
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c
new file mode 100644
index 0000000000..3aeaeb9091
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c
@@ -0,0 +1,628 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include "NorFlashHw.h"
+
+
+BOOLEAN gFlashBusy = FALSE;
+FLASH_INDEX gIndex = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+UINT32 PortReadData (
+ UINT32 Index,
+ UINT32 FlashAddr
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ return MmioRead32 (FlashAddr);
+ case 1:
+ return MmioRead16 (FlashAddr);
+
+ default:
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
+ return 0xffffffff;
+ }
+}
+
+EFI_STATUS
+PortWriteData (
+ UINT32 Index,
+ UINT32 FlashAddr,
+ UINT32 InputData
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ MmioWrite32 (FlashAddr, InputData);
+ break;
+ case 1:
+ MmioWrite16 (FlashAddr, InputData);
+ break;
+ default:
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+UINT32 PortAdjustData(
+ UINT32 Index,
+ UINT32 ulInputData
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ return ulInputData;
+ case 1:
+ return (0x0000ffff & ulInputData );
+ default:
+ DEBUG((EFI_D_ERROR,"[FLASH_S29GL256N_PortAdjustData]: Error--illegal g_ulFlashS29Gl256NPortWidth!\n\r"));
+ return 0xffffffff;
+ }
+}
+
+
+EFI_STATUS GetCommandIndex(
+ UINT32 Index
+ )
+{
+ UINT32 CommandCount = 0;
+ UINT32 i;
+ UINT8 Flag = 1;
+
+ CommandCount = sizeof(gFlashCommandReset) / sizeof(FLASH_COMMAND_RESET);
+ for(i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandReset[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.ReIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Reset Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandId) / sizeof(FLASH_COMMAND_ID);
+ for(Flag = 1,i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandId[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.IdIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get ID Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandWrite) / sizeof(FLASH_COMMAND_WRITE);
+ for(Flag = 1, i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandWrite[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.WIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Write Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandErase) / sizeof(FLASH_COMMAND_ERASE);
+ for(Flag = 1, i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandErase[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.WIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Erase Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID FlashReset(UINT32 Base)
+{
+ (VOID)PortWriteData(gIndex.InfIndex, Base, gFlashCommandReset[gIndex.ReIndex].ResetData);
+ (void)gBS->Stall(20000);
+}
+
+
+void GetManufacturerID(UINT32 Index, UINT32 Base, UINT8 *pbyData)
+{
+
+ UINT32 dwAddr;
+
+ FlashReset(Base);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
+
+ *pbyData = (UINT8)PortReadData(Index, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[Index].ParallelNum));
+
+ FlashReset(Base); //must reset to return to the read mode
+}
+
+
+EFI_STATUS FlashInit(UINT32 Base)
+{
+ UINT32 FlashCount = 0;
+ UINT32 i = 0;
+ EFI_STATUS Status;
+ UINT8 Flag = 1;
+ UINT32 TempData = 0;
+ UINT32 TempDev1 = 0;
+ UINT32 TempDev2 = 0;
+ UINT32 TempDev3 = 0;
+ UINT32 dwAddr;
+
+ FlashCount = sizeof(gFlashInfo) / sizeof(NOR_FLASH_INFO_TABLE);
+ for(;i < FlashCount; i ++ )
+ {
+
+ Status = GetCommandIndex(i);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Get Command Index %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ FlashReset(Base);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
+ //Get manufacture ID
+ TempData = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[i].ParallelNum));
+
+ //Get Device Id
+ TempDev1 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress1 << gFlashInfo[i].ParallelNum));
+ TempDev2 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress2 << gFlashInfo[i].ParallelNum));
+ TempDev3 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress3 << gFlashInfo[i].ParallelNum));
+ DEBUG ((EFI_D_ERROR, "[cdtest]manufactor ID 0x%x!\n",TempData));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 1 0x%x!\n",TempDev1));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 2 0x%x!\n",TempDev2));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 3 0x%x!\n",TempDev3));
+
+ FlashReset(Base);
+
+
+ if((0xffffffff != TempData)
+ && (PortAdjustData(i, gFlashInfo[i].ManufacturerID) == TempData))
+ {
+ if((0xffffffff != TempDev1)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID1) == TempDev1))
+ {
+ if((0xffffffff != TempDev2)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID2) == TempDev2))
+ {
+ if((0xffffffff != TempDev3)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID3) == TempDev3))
+ {
+ Flag = 0;
+ gIndex.InfIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(Flag)
+ {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+static BOOLEAN width8IsAll(
+ const UINT64 Base,
+ const UINT64 Offset,
+ const UINT64 Length,
+ const UINT8 Value
+)
+{
+ UINT64 NewAddr = Base + Offset;
+ UINT64 NewLength = Length;
+ while (NewLength --)
+ {
+ if (*(UINT8 *)(UINTN)NewAddr == Value)
+ {
+ NewAddr ++;
+ continue;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+
+EFI_STATUS BufferWriteCommand(UINTN Base, UINTN Offset, void *pData)
+{
+ UINT32 dwCommAddr;
+ UINT32 *pdwData;
+ UINT16 *pwData;
+ UINT32 dwLoop;
+ UINT32 ulWriteWordCount;
+ UINT32 dwAddr;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+ gFlashBusy = TRUE;
+
+ if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
+ {
+ pdwData = (UINT32 *)pData;
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
+
+ //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
+
+
+ ulWriteWordCount = ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << 16) | (gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
+
+
+ for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
+ {
+ dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ MmioWrite32 (dwCommAddr, *pdwData);
+ pdwData ++;
+ }
+
+ dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
+
+
+
+ }
+ else
+ {
+ pwData = (UINT16 *)pData;
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
+
+ //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
+
+
+ ulWriteWordCount = gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
+
+
+ for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
+ {
+ dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ MmioWrite16 (dwCommAddr, *pwData);
+ pwData ++;
+ }
+
+ dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
+
+ }
+
+ (void)gBS->Stall(200);
+
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS SectorEraseCommand(UINTN Base, UINTN Offset)
+{
+ UINT32 dwAddr;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+
+ gFlashBusy = TRUE;
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep2);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep3 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep3);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep4 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep4);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep5 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep5);
+
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep6);
+
+ (void)gBS->Stall(500000);
+
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS CompleteCheck(UINT32 Base, UINT32 Offset, void *pData, UINT32 Length)
+{
+ UINT32 dwTestAddr;
+ UINT32 dwTestData;
+ UINT32 dwTemp = 0;
+ UINT32 dwTemp1 = 0;
+ UINT32 i;
+ UINT32 dwTimeOut = 3000000;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+ gFlashBusy = TRUE;
+
+ if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
+ {
+ dwTestAddr = Base + Offset + Length - sizeof(UINT32);
+ dwTestData = *((UINT32 *)((UINT8 *)pData + Length - sizeof(UINT32)));
+
+ while(dwTimeOut--)
+ {
+ dwTemp1 = MmioRead32 (dwTestAddr);
+ if (dwTestData == dwTemp1)
+ {
+ dwTemp = MmioRead32 (dwTestAddr);
+ dwTemp1 = MmioRead32 (dwTestAddr);
+ if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
+ {
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+ }
+ }
+
+ (void)gBS->Stall(1);
+ }
+
+ if((UINT16)(dwTemp1 >> 16) != (UINT16)(dwTestData >> 16))
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip1 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
+ }
+ if((UINT16)(dwTemp1) != (UINT16)(dwTestData))
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip2 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
+ }
+ }
+ else
+ {
+ dwTestAddr = Base + Offset + Length - sizeof(UINT16);
+ dwTestData = *((UINT16 *)((UINT8 *)pData + Length - sizeof(UINT16)));
+
+ while(dwTimeOut--)
+ {
+ dwTemp1 = MmioRead16 (dwTestAddr);
+ if (dwTestData == dwTemp1)
+ {
+ dwTemp = MmioRead16 (dwTestAddr);
+ dwTemp1 = MmioRead16 (dwTestAddr);
+ if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
+ {
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+ }
+ }
+
+ (void)gBS->Stall(1);
+ }
+ }
+
+ for(i = 0; i < 5; i ++)
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: flash %x\n",PortReadData(gIndex.InfIndex, dwTestAddr)));
+ }
+
+ FlashReset(Base);
+
+ gFlashBusy = FALSE;
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: timeout address %x, buffer %x, flash %x\n", Offset, dwTestData, dwTemp1));
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS IsNeedToWrite(
+ IN UINT32 Base,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ UINTN NewAddr = Base + Offset;
+ UINT8 FlashData = 0;
+ UINT8 BufferData = 0;
+
+ for(; Length > 0; Length --)
+ {
+ BufferData = *Buffer;
+ //lint -epn -e511
+ FlashData = *(UINT8 *)NewAddr;
+ if (BufferData != FlashData)
+ {
+ return TRUE;
+ }
+ NewAddr ++;
+ Buffer ++;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length)
+{
+ EFI_STATUS Status;
+ UINT32 dwLoop;
+ UINT32 Retry = 3;
+
+ if (FALSE == IsNeedToWrite(gIndex.Base, Offset, (UINT8 *)pData, Length))
+ {
+ return EFI_SUCCESS;
+ }
+
+ do
+ {
+ (void)BufferWriteCommand(gIndex.Base, Offset, pData);
+ Status = CompleteCheck(gIndex.Base, Offset, pData, Length);
+
+
+ if (EFI_SUCCESS == Status)
+ {
+ for (dwLoop = 0; dwLoop < Length; dwLoop ++)
+ {
+ if (*(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop) != *((UINT8 *)pData + dwLoop))
+ {
+ DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: address %x, buffer %x, flash %x\n", Offset, *((UINT8 *)pData + dwLoop), *(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop)));
+ Status = EFI_ABORTED;
+ continue;
+ }
+ }
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: complete check failed, %r\n", Status));
+ continue;
+ }
+ } while ((Retry--) && EFI_ERROR(Status));
+
+ return Status;
+}
+
+
+EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset)
+{
+ UINT8 gTemp[FLASH_MAX_UNIT];
+ UINT64 dwLoop = FLASH_MAX_UNIT - 1;
+ UINT32 Retry = 3;
+ EFI_STATUS Status;
+
+ do
+ {
+ gTemp[dwLoop] = 0xFF;
+ }while (dwLoop --);
+
+ do
+ {
+ (void)SectorEraseCommand(Base, Offset);
+ Status = CompleteCheck(Base, Offset, (void *)gTemp, FLASH_MAX_UNIT);
+
+
+ if (EFI_SUCCESS == Status)
+ {
+
+ if (width8IsAll(Base,Offset - (Offset % gFlashInfo[gIndex.InfIndex].BlockSize), gFlashInfo[gIndex.InfIndex].BlockSize, 0xFF))
+ {
+ return EFI_SUCCESS;
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: not all address equal 0xFF\n"));
+
+ Status = EFI_ABORTED;
+ continue;
+ }
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: complete check failed, %r\n", Status));
+ continue;
+ }
+ }while ((Retry--) && EFI_ERROR(Status));
+
+ if(Retry)
+ {
+ //do nothing for pclint
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h
new file mode 100644
index 0000000000..36c0c9ec23
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h
@@ -0,0 +1,116 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _NOR_FLASH_HW_H_
+#define _NOR_FLASH_HW_H_
+
+#include <Uefi/UefiBaseType.h>
+
+
+#define FOUR_BYTE_UNIT 4
+#define FLASH_MAX_UNIT 4
+
+#define FLASH_DEVICE_NUM 0x10
+
+
+
+typedef struct {
+ UINT32 ManufacturerID;
+ UINT32 DeviceID1;
+ UINT32 DeviceID2;
+ UINT32 DeviceID3;
+ UINT8 ParallelNum;
+ UINT32 SingleChipSize;
+ UINT32 BlockSize;
+ UINT32 BufferProgramSize;
+ UINT32 CommandType;
+}NOR_FLASH_INFO_TABLE;
+
+/*Define Command Address And Data*/
+/*reset*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 ResetData;
+}FLASH_COMMAND_RESET;
+
+/*manufacture ID & Device ID*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 ManuIDAddressStep1;
+ UINT32 ManuIDDataStep1;
+ UINT32 ManuIDAddressStep2;
+ UINT32 ManuIDDataStep2;
+ UINT32 ManuIDAddressStep3;
+ UINT32 ManuIDDataStep3;
+ UINT32 ManuIDAddress;
+
+ UINT32 DeviceIDAddress1;
+ UINT32 DeviceIDAddress2;
+ UINT32 DeviceIDAddress3;
+}FLASH_COMMAND_ID;
+
+/*Write Buffer*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 BufferProgramAddressStep1;
+ UINT32 BufferProgramDataStep1;
+ UINT32 BufferProgramAddressStep2;
+ UINT32 BufferProgramDataStep2;
+ UINT32 BufferProgramDataStep3;
+ UINT32 BufferProgramtoFlash;
+}FLASH_COMMAND_WRITE;
+
+/*erase*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 SectorEraseAddressStep1;
+ UINT32 SectorEraseDataStep1;
+ UINT32 SectorEraseAddressStep2;
+ UINT32 SectorEraseDataStep2;
+ UINT32 SectorEraseAddressStep3;
+ UINT32 SectorEraseDataStep3;
+ UINT32 SectorEraseAddressStep4;
+ UINT32 SectorEraseDataStep4;
+ UINT32 SectorEraseAddressStep5;
+ UINT32 SectorEraseDataStep5;
+ UINT32 SectorEraseDataStep6;
+}FLASH_COMMAND_ERASE;
+
+
+typedef struct {
+ UINT32 Base;
+ UINT32 InfIndex;
+ UINT32 ReIndex;
+ UINT32 IdIndex;
+ UINT32 WIndex;
+ UINT32 EIndex;
+}FLASH_INDEX;
+
+
+extern EFI_STATUS FlashInit(UINT32 Base);
+extern EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset);
+extern EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length);
+extern EFI_STATUS IsNeedToWrite(UINT32 Base, UINT32 Offset, UINT8 *Buffer, UINT32 Length);
+
+
+extern NOR_FLASH_INFO_TABLE gFlashInfo[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_RESET gFlashCommandReset[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_ID gFlashCommandId[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_WRITE gFlashCommandWrite[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_ERASE gFlashCommandErase[FLASH_DEVICE_NUM];
+extern FLASH_INDEX gIndex;
+
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644
index 0000000000..a970da65df
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.c
@@ -0,0 +1,1651 @@
+/**
+ * Copyright (c) 2014, AppliedMicro Corp. All rights reserved.
+ * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ * Copyright (c) 2016, Linaro Limited. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ *
+ **/
+
+#include <Uefi.h>
+#include <Protocol/EmbeddedGpio.h>
+#include <Guid/EventGroup.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/OemMiscLib.h>
+
+#include "PciHostBridge.h"
+
+UINTN RootBridgeNumber[PCIE_MAX_HOSTBRIDGE] = { PCIE_MAX_ROOTBRIDGE,PCIE_MAX_ROOTBRIDGE };
+
+UINT64 RootBridgeAttribute[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = {
+ { //Host Bridge0
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ },
+ { //Host Bridge1
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ }
+ };
+
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = {
+ { //Host Bridge0
+ /* Port 0 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A03),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 1 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A04),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 2 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A05),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 3 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A06),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 4 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A07),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 5 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A08),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 6 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A09),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 7 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0A),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ }
+},
+{ // Host Bridge1
+ /* Port 0 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0B),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 1 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0C),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 2 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0D),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 3 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0E),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 4 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A0F),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 5 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A10),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 6 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A11),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ /* Port 7 */
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A12),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ }
+ }
+};
+
+EFI_HANDLE mDriverImageHandle;
+
+PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
+ PCI_HOST_BRIDGE_SIGNATURE, // Signature
+ NULL, // HostBridgeHandle
+ 0, // RootBridgeNumber
+ {NULL, NULL}, // Head
+ FALSE, // ResourceSubiteed
+ TRUE, // CanRestarted
+ {
+ NotifyPhase,
+ GetNextRootBridge,
+ GetAttributes,
+ StartBusEnumeration,
+ SetBusNumbers,
+ SubmitResources,
+ GetProposedResources,
+ PreprocessController
+ }
+};
+
+/**
+ Entry point of this driver
+
+ @param ImageHandle Handle of driver image
+ @param SystemTable Point to EFI_SYSTEM_TABLE
+
+ @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
+ @retval EFI_DEVICE_ERROR Can not install the protocol instance
+ @retval EFI_SUCCESS Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Loop1;
+ UINTN Loop2;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge = NULL;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINT32 PcieRootBridgeMask;
+
+ if (!OemIsMpBoot())
+ {
+ PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask);
+ }
+ else
+ {
+ PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask2P);
+ }
+
+ mDriverImageHandle = ImageHandle;
+ //
+ // Create Host Bridge Device Handle
+ //
+ //Each Host Bridge have 8 Root Bridges max, every bits of 0xFF(8 bit) stands for the according PCIe Port
+ //is enable or not
+ for (Loop1 = 0; Loop1 < PCIE_MAX_HOSTBRIDGE; Loop1++) {
+ if (((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) & 0xFF ) == 0) {
+ continue;
+ }
+
+
+ HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
+ if (HostBridge == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
+ InitializeListHead (&HostBridge->Head);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Create Root Bridge Device Handle in this Host Bridge
+ //
+ for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
+ if (!(((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) >> Loop2 ) & 0x01)) {
+ continue;
+ }
+
+ PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
+ if (PrivateData == NULL) {
+ FreePool (HostBridge);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ PrivateData->Port = Loop2;
+ PrivateData->SocType = PcdGet32(Pcdsoctype);
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
+
+ (VOID)RootBridgeConstructor (
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ RootBridgeAttribute[Loop1][Loop2],
+ &mResAppeture[Loop1][Loop2],
+ Loop1
+ );
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid, PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ (VOID)gBS->UninstallMultipleProtocolInterfaces (
+ HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ NULL
+ );
+ FreePool(PrivateData);
+ FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+ // PCI Memory Space
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mResAppeture[Loop1][Loop2] .MemBase,
+ mResAppeture[Loop1][Loop2] .MemLimit -mResAppeture[Loop1][Loop2] .MemBase + 1,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR,"PCIE AddMemorySpace Error\n"));
+ }
+ InsertTailList (&HostBridge->Head, &PrivateData->Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+NotifyAllocateMemResources(
+ IN PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance,
+ IN PCI_RESOURCE_TYPE Index,
+ IN OUT UINT64 *AllocatedLenMem
+)
+{
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_STATUS ReturnStatus;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ PCIE_DEBUG("Addrlen:%llx\n", AddrLen);
+ // Get the number of '1' in Alignment.
+ BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1);
+
+ BaseAddress = (RootBridgeInstance->MemBase + *AllocatedLenMem +
+ RootBridgeInstance->ResAllocNode[Index].Alignment)
+ & ~(RootBridgeInstance->ResAllocNode[Index].Alignment);
+ if ((BaseAddress + AddrLen - 1) > RootBridgeInstance->MemLimit) {
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ return ReturnStatus;
+ }
+
+ PCIE_DEBUG("(P)Mem32/64 request memory at:%llx\n", BaseAddress);
+ ReturnStatus = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (ReturnStatus)) {
+ // We were able to allocate the PCI memory
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ *AllocatedLenMem += AddrLen;
+ PCIE_DEBUG("(P)Mem32/64 resource allocated:%llx\n", BaseAddress);
+
+ } else {
+ // Not able to allocate enough PCI memory
+ if (ReturnStatus != EFI_OUT_OF_RESOURCES) {
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ }
+ }
+ return ReturnStatus;
+}
+
+EFI_STATUS
+EFIAPI
+NotifyAllocateResources(
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance
+)
+{
+ EFI_STATUS ReturnStatus;
+ LIST_ENTRY *List;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+
+ ReturnStatus = EFI_SUCCESS;
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+
+ UINT64 AllocatedLenMem = 0;
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ if(Index == TypeIo) {
+ PCIE_DEBUG("NOT SUPPOER IO RESOURCES ON THIS PLATFORM\n");
+ } else if ((Index >= TypeMem32) && (Index <= TypePMem64)) {
+ ReturnStatus = NotifyAllocateMemResources(RootBridgeInstance,Index,&AllocatedLenMem);
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return ReturnStatus;
+}
+
+EFI_STATUS
+EFIAPI
+NotifyFreeResources(
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance
+)
+{
+ EFI_STATUS ReturnStatus;
+ LIST_ENTRY *List;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+ UINT64 AddrLen;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+ ReturnStatus = EFI_SUCCESS;
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
+
+ if(Index <= TypePMem64){
+ ReturnStatus = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+ }else{
+ ASSERT (FALSE);
+ }
+
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ return ReturnStatus;
+
+}
+
+VOID
+EFIAPI
+NotifyBeginEnumeration(
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance
+)
+{
+ LIST_ENTRY *List;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+
+ //
+ // Reset the Each Root Bridge
+ //
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+}
+
+/**
+ These are the notifications from the PCI bus driver that it is about to enter a certain
+ phase of the PCI enumeration process.
+
+ This member function can be used to notify the host bridge driver to perform specific actions,
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+ Eight notification points are defined at this time. See belows:
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
+ structures. The PCI enumerator should issue this notification
+ before starting a fresh enumeration process. Enumeration cannot
+ be restarted after sending any other notification such as
+ EfiPciHostBridgeBeginBusAllocation.
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
+ required here. This notification can be used to perform any
+ chipset-specific programming.
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
+ specific action is required here. This notification can be used to
+ perform any chipset-specific programming.
+ EfiPciHostBridgeBeginResourceAllocation
+ The resource allocation phase is about to begin. No specific
+ action is required here. This notification can be used to perform
+ any chipset-specific programming.
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
+ root bridges. These resource settings are returned on the next call to
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+ for gathering I/O and memory requests for
+ all the PCI root bridges and submitting these requests using
+ SubmitResources(). This function pads the resource amount
+ to suit the root bridge hardware, takes care of dependencies between
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)
+ with the allocation request. In the case of padding, the allocated range
+ could be bigger than what was requested.
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
+ resources (proposed resources) for all the PCI root bridges. After the
+ hardware is programmed, reassigning resources will not be supported.
+ The bus settings are not affected.
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
+ root bridges and resets the I/O and memory apertures to their initial
+ state. The bus settings are not affected. If the request to allocate
+ resources fails, the PCI enumerator can use this notification to
+ deallocate previous resources, adjust the requests, and retry
+ allocation.
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
+ required here. This notification can be used to perform any chipsetspecific
+ programming.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] Phase The phase during enumeration
+
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if
+ SubmitResources() has not been called for one or more
+ PCI root bridges before this call
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
+ for a Phase of EfiPciHostBridgeSetResources.
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+ previously submitted resource requests cannot be fulfilled or
+ were only partially fulfilled.
+ @retval EFI_SUCCESS The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ EFI_STATUS ReturnStatus;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ ReturnStatus = EFI_SUCCESS;
+
+ switch (Phase) {
+
+ case EfiPciHostBridgeBeginEnumeration:
+ PCIE_DEBUG("Case EfiPciHostBridgeBeginEnumeration\n");
+ if (HostBridgeInstance->CanRestarted) {
+ NotifyBeginEnumeration(HostBridgeInstance);
+ } else {
+ //
+ // Can not restart
+ //
+ return EFI_NOT_READY;
+ }
+ break;
+
+ case EfiPciHostBridgeEndEnumeration:
+ PCIE_DEBUG("Case EfiPciHostBridgeEndEnumeration\n");
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ PCIE_DEBUG("Case EfiPciHostBridgeBeginBusAllocation\n");
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+
+ HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ PCIE_DEBUG("Case EfiPciHostBridgeEndBusAllocation\n");
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ PCIE_DEBUG("Case EfiPciHostBridgeBeginResourceAllocation\n");
+ //
+ // No specific action is required here, can perform any chipset specific programing
+ //
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ PCIE_DEBUG("Case EfiPciHostBridgeAllocateResources\n");
+
+ if (HostBridgeInstance->ResourceSubmited) {
+ //
+ // Take care of the resource dependencies between the root bridges
+ //
+ ReturnStatus = NotifyAllocateResources(HostBridgeInstance);
+ } else {
+ return EFI_NOT_READY;
+ }
+ //break;
+
+ case EfiPciHostBridgeSetResources:
+ PCIE_DEBUG("Case EfiPciHostBridgeSetResources\n");
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ PCIE_DEBUG("Case EfiPciHostBridgeFreeResources\n");
+
+ ReturnStatus = NotifyFreeResources(HostBridgeInstance);
+ break;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ PCIE_DEBUG("Case EfiPciHostBridgeEndResourceAllocation\n");
+ HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return ReturnStatus;
+}
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+
+ This function is called multiple times to retrieve the device handles of all the PCI root bridges that
+ are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
+ root bridges. On each call, the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next PCI root bridge. The
+ caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ for that root bridge. When there are no more PCI root bridges to report, the interface returns
+ EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
+ are returned by this function.
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+{
+ BOOLEAN NoRootBridge;
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ NoRootBridge = TRUE;
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+
+ while (List != &HostBridgeInstance->Head) {
+ NoRootBridge = FALSE;
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (*RootBridgeHandle == NULL) {
+ //
+ // Return the first Root Bridge Handle of the Host Bridge
+ //
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ if (*RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Get next if have
+ //
+ List = List->ForwardLink;
+ if (List!=&HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ List = List->ForwardLink;
+ } //end while
+
+ if (NoRootBridge) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
+ from one PCI root bridge to another. These attributes are different from the decode-related
+ attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
+ handles of all the root bridges that are associated with this host bridge must be obtained by calling
+ GetNextRootBridge(). The attributes are static in the sense that they do not change during or
+ after the enumeration process. The hardware may provide mechanisms to change the attributes on
+ the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
+ installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
+ include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
+ prefetchable memory.
+ Attribute Description
+ ------------------------------------ ----------------------------------------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
+ windows for nonprefetchable and prefetchable memory. A PCI bus
+ driver needs to include requests for prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
+ windows. If this bit is not set, the PCI bus driver needs to include
+ requests for a 64-bit memory address in the corresponding 32-bit
+ memory pool.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
+ EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+ @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ if (Attributes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ *Attributes = RootBridgeInstance->RootBridgeAttrib;
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ //
+ // RootBridgeHandle is not an EFI_HANDLE
+ // that was returned on a previous call to GetNextRootBridge()
+ //
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Sets up the specified PCI root bridge for the bus enumeration process.
+
+ This member function sets up the root bridge for bus enumeration and returns the PCI bus range
+ over which the search should be performed in ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ VOID *Buffer;
+ UINT8 *Temp;
+ UINT64 BusStart;
+ UINT64 BusEnd;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ //
+ // Set up the Root Bridge for Bus Enumeration
+ //
+ BusStart = RootBridgeInstance->BusBase;
+ BusEnd = RootBridgeInstance->BusLimit;
+ //
+ // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+ //
+
+ Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Temp = (UINT8 *)Buffer;
+
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
+
+ Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+ }
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
+
+ This member function programs the specified PCI root bridge to decode the bus range that is
+ specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
+ bus descriptors.
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = Configuration;
+
+ //
+ // Check the Configuration is valid
+ //
+ if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Ptr = Configuration;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
+ BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+
+ if (BusStart > BusEnd) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update the Bus Range
+ //
+ RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
+ RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
+ RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
+
+ //
+ // Program the Root Bridge Hardware
+ //
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+VOID
+EFIAPI
+SubmitGetResourceType(
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr,
+ OUT UINT64* Index
+)
+{
+ switch (Ptr->ResType) {
+ case 0:
+ if (Ptr->AddrSpaceGranularity == 32) {
+ if (Ptr->SpecificFlag == 0x06)
+ *Index = TypePMem32;
+ else
+ *Index = TypeMem32;
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+ if (Ptr->SpecificFlag == 0x06)
+ *Index = TypePMem64;
+ else
+ *Index = TypeMem64;
+ }
+ break;
+
+ case 1:
+ *Index = TypeIo;
+ break;
+
+ default:
+ break;
+ };
+
+}
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI root bridge.
+
+ This function is used to submit all the I/O and memory resources that are required by the specified
+ PCI root bridge. The input parameter Configuration is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
+ not supported by this PCI root bridge. This error will happen if the caller
+ did not combine resources according to Attributes that were returned by
+ GetAllocAttributes().
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 AddrLen;
+ UINT64 Alignment;
+ UINTN Index;
+
+ PCIE_DEBUG("In SubmitResources\n");
+ //
+ // Check the input parameter: Configuration
+ //
+ if (Configuration == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ Temp = (UINT8 *)Configuration;
+ while ( *Temp == 0x8A)
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+
+ if (*Temp != 0x79)
+ return EFI_INVALID_PARAMETER;
+
+ Temp = (UINT8 *)Configuration;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ while ( *Temp == 0x8A) {
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
+ PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType);
+ PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen);
+ PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax);
+ PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin);
+ PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag);
+ PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity);
+ PCIE_DEBUG("RootBridgeInstance->RootBridgeAttrib:%llx\n", RootBridgeInstance->RootBridgeAttrib);
+ //
+ // Check address range alignment
+ //
+ if (Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Index = 0;
+ SubmitGetResourceType(Ptr,&Index);
+ AddrLen = (UINTN) Ptr->AddrLen;
+ Alignment = (UINTN) Ptr->AddrRangeMax;
+ RootBridgeInstance->ResAllocNode[Index].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[Index].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+SetResource(
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance,
+ VOID *Buffer
+
+)
+{
+ UINTN Index;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 ResStatus;
+
+ Temp = Buffer;
+
+ for (Index = 0; Index < TypeBus; Index ++)
+ {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
+ ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
+
+ switch (Index) {
+
+ case TypeIo:
+ //
+ // Io
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 1;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ /* This is PCIE Device Bus which start address is the low 32bit of mem base*/
+ Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) +
+ (RootBridgeInstance->MemBase & 0xFFFFFFFF);
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem32:
+ //
+ // Memory 32
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ Ptr->AddrSpaceGranularity = 32;
+ /* This is PCIE Device Bus which start address is the low 32bit of mem base*/
+ Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) +
+ (RootBridgeInstance->MemBase & 0xFFFFFFFF);
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem32:
+ //
+ // Prefetch memory 32
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 6;
+ Ptr->AddrSpaceGranularity = 32;
+ /* This is PCIE Device Bus which start address is the low 32bit of mem base*/
+ Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) +
+ (RootBridgeInstance->MemBase & 0xFFFFFFFF);
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem64:
+ //
+ // Memory 64
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 0;
+ Ptr->AddrSpaceGranularity = 64;
+ /* This is PCIE Device Bus which start address is the low 32bit of mem base*/
+ Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) +
+ (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF);
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem64:
+ //
+ // Prefetch memory 64
+ //
+ Ptr->Desc = 0x8A;
+ Ptr->Len = 0x2B;
+ Ptr->ResType = 0;
+ Ptr->GenFlag = 0;
+ Ptr->SpecificFlag = 6;
+ Ptr->AddrSpaceGranularity = 64;
+ /* This is PCIE Device Bus which start address is the low 32bit of mem base*/
+ Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) +
+ (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF);
+ Ptr->AddrRangeMax = 0;
+ Ptr->AddrTranslationOffset = \
+ (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+ };
+ PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType);
+ PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen);
+ PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax);
+ PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin);
+ PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag);
+ PCIE_DEBUG("Ptr->AddrTranslationOffset:%d\n", Ptr->AddrTranslationOffset);
+ PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity);
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+ return EFI_SUCCESS;
+}
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINTN Index;
+ UINTN Number;
+ VOID *Buffer;
+
+ Buffer = NULL;
+ Number = 0;
+
+ PCIE_DEBUG("In GetProposedResources\n");
+ //
+ // Get the Host Bridge Instance from the resource allocation protocol
+ //
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ //
+ // Enumerate the root bridges in this host bridge
+ //
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ for (Index = 0; Index < TypeBus; Index ++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Number ++;
+ }
+ }
+
+ Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (VOID)SetResource(RootBridgeInstance,Buffer);
+
+ *Configuration = Buffer;
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration.
+
+ This function is called during the PCI enumeration process. No specific action is expected from this
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+ enumeration.
+
+ @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
+ configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
+ the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+ @param Phase The phase of the PCI device enumeration.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
+ not enumerate this device, including its child devices if it is a PCI-to-PCI
+ bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ LIST_ENTRY *List;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ //
+ // Enumerate the root bridges in this host bridge
+ //
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ break;
+ }
+ List = List->ForwardLink;
+ }
+ if (List == &HostBridgeInstance->Head) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h
new file mode 100644
index 0000000000..cddda6b642
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridge.h
@@ -0,0 +1,521 @@
+/**
+ * Copyright (c) 2014, AppliedMicro Corp. All rights reserved.
+ * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ * Copyright (c) 2016, Linaro Limited. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ *
+ **/
+
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/Metronome.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/CpuIo2.h>
+
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformPciLib.h>
+
+// Enable below statments to enable PCIE debug
+//#define PCIE_DEBUG_ENABLE
+//#define PCIE_VDEBUG_ENABLE
+//#define PCIE_CDEBUG_ENABLE
+
+#ifdef PCIE_CDEBUG_ENABLE
+# define PCIE_CSR_DEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg))
+#else
+# define PCIE_CSR_DEBUG(arg...)
+#endif
+
+#ifdef PCIE_VDEBUG_ENABLE
+# define PCIE_VDEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg))
+#else
+# define PCIE_VDEBUG(arg...)
+#endif
+
+#ifdef PCIE_DEBUG_ENABLE
+# define PCIE_DEBUG(arg...) DEBUG((EFI_D_VERBOSE,## arg))
+#else
+# define PCIE_DEBUG(arg...)
+#endif
+#define PCIE_WARN(arg...) DEBUG((EFI_D_WARN,## arg))
+#define PCIE_ERR(arg...) DEBUG((EFI_D_ERROR,## arg))
+#define PCIE_INFO(arg...) DEBUG((EFI_D_INFO,## arg))
+
+#define MAX_PCI_DEVICE_NUMBER 31
+#define MAX_PCI_FUNCTION_NUMBER 7
+#define MAX_PCI_REG_ADDRESS 0xFFFF
+
+typedef enum {
+ IoOperation,
+ MemOperation,
+ PciOperation
+} OPERATION_TYPE;
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32('e', 'h', 's', 't')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE HostBridgeHandle;
+ UINTN RootBridgeNumber;
+ LIST_ENTRY Head;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
+ CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+//
+// HostBridge Resource Allocation interface
+//
+
+/**
+ These are the notifications from the PCI bus driver that it is about to enter a certain
+ phase of the PCI enumeration process.
+
+ This member function can be used to notify the host bridge driver to perform specific actions,
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+ Eight notification points are defined at this time. See belows:
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
+ structures. The PCI enumerator should issue this notification
+ before starting a fresh enumeration process. Enumeration cannot
+ be restarted after sending any other notification such as
+ EfiPciHostBridgeBeginBusAllocation.
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
+ required here. This notification can be used to perform any
+ chipset-specific programming.
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
+ specific action is required here. This notification can be used to
+ perform any chipset-specific programming.
+ EfiPciHostBridgeBeginResourceAllocation
+ The resource allocation phase is about to begin. No specific
+ action is required here. This notification can be used to perform
+ any chipset-specific programming.
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
+ root bridges. These resource settings are returned on the next call to
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+ for gathering I/O and memory requests for
+ all the PCI root bridges and submitting these requests using
+ SubmitResources(). This function pads the resource amount
+ to suit the root bridge hardware, takes care of dependencies between
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)
+ with the allocation request. In the case of padding, the allocated range
+ could be bigger than what was requested.
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
+ resources (proposed resources) for all the PCI root bridges. After the
+ hardware is programmed, reassigning resources will not be supported.
+ The bus settings are not affected.
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
+ root bridges and resets the I/O and memory apertures to their initial
+ state. The bus settings are not affected. If the request to allocate
+ resources fails, the PCI enumerator can use this notification to
+ deallocate previous resources, adjust the requests, and retry
+ allocation.
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
+ required here. This notification can be used to perform any chipsetspecific
+ programming.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] Phase The phase during enumeration
+
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if
+ SubmitResources() has not been called for one or more
+ PCI root bridges before this call
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
+ for a Phase of EfiPciHostBridgeSetResources.
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+ previously submitted resource requests cannot be fulfilled or
+ were only partially fulfilled.
+ @retval EFI_SUCCESS The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+
+ This function is called multiple times to retrieve the device handles of all the PCI root bridges that
+ are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
+ root bridges. On each call, the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next PCI root bridge. The
+ caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ for that root bridge. When there are no more PCI root bridges to report, the interface returns
+ EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
+ are returned by this function.
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ );
+
+/**
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
+ from one PCI root bridge to another. These attributes are different from the decode-related
+ attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
+ handles of all the root bridges that are associated with this host bridge must be obtained by calling
+ GetNextRootBridge(). The attributes are static in the sense that they do not change during or
+ after the enumeration process. The hardware may provide mechanisms to change the attributes on
+ the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
+ installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
+ include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
+ prefetchable memory.
+ Attribute Description
+ ------------------------------------ ----------------------------------------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
+ windows for nonprefetchable and prefetchable memory. A PCI bus
+ driver needs to include requests for prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
+ windows. If this bit is not set, the PCI bus driver needs to include
+ requests for a 64-bit memory address in the corresponding 32-bit
+ memory pool.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
+ EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+ @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets up the specified PCI root bridge for the bus enumeration process.
+
+ This member function sets up the root bridge for bus enumeration and returns the PCI bus range
+ over which the search should be performed in ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
+
+ This member function programs the specified PCI root bridge to decode the bus range that is
+ specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
+ bus descriptors.
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI root bridge.
+
+ This function is used to submit all the I/O and memory resources that are required by the specified
+ PCI root bridge. The input parameter Configuration is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
+ not supported by this PCI root bridge. This error will happen if the caller
+ did not combine resources according to Attributes that were returned by
+ GetAllocAttributes().
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration.
+
+ This function is called during the PCI enumeration process. No specific action is expected from this
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+ enumeration.
+
+ @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
+ configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
+ the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+ @param Phase The phase of the PCI device enumeration.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
+ not enumerate this device, including its child devices if it is a PCI-to-PCI
+ bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+
+
+//
+// Driver Instance Data Prototypes
+//
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef enum {
+ TypeIo = 0,
+ TypeMem32,
+ TypePMem32,
+ TypeMem64,
+ TypePMem64,
+ TypeBus,
+ TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+ ResNone = 0,
+ ResSubmitted,
+ ResRequested,
+ ResAllocated,
+ ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+ PCI_RESOURCE_TYPE Type;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+ RES_STATUS Status;
+} PCI_RES_NODE;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('e', '2', 'p', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ UINT64 RootBridgeAttrib;
+ UINT64 Attributes;
+ UINT64 Supports;
+
+ //
+ // Specific for this memory controller: Bus, I/O, Mem
+ //
+ PCI_RES_NODE ResAllocNode[6];
+
+ //
+ // Addressing for Memory and I/O and Bus arrange
+ //
+ UINT64 BusBase;
+ UINT64 MemBase;
+ UINT64 IoBase;
+ UINT64 BusLimit;
+ UINT64 MemLimit;
+ UINT64 IoLimit;
+ UINT64 RbPciBar;
+ UINT64 Ecam;
+
+ UINTN PciAddress;
+ UINTN PciData;
+ UINTN Port;
+ UINT32 SocType;
+ UINT64 CpuMemRegionBase;
+ UINT64 CpuIoRegionBase;
+ UINT64 PciRegionBase;
+ UINT64 PciRegionLimit;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+
+ Construct the Pci Root Bridge Io protocol
+
+ @param Protocol Point to protocol instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param ResAppeture ResourceAppeture for host bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture,
+ IN UINT32 Seg
+ );
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000000..7f5e1751ec
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,74 @@
+## @file
+#
+# Component description file PCI Host Bridge driver.
+# Copyright (c) 2014, AppliedMicro Corp. All rights reserved.
+# Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciHostBridge
+ FILE_GUID = B0E61270-263F-11E3-8224-0800200C9A66
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializePciHostBridge
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ CacheMaintenanceLib
+ DmaLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ TimerLib
+ ArmLib
+ DevicePathLib
+ PcdLib
+ OemMiscLib
+
+[Sources]
+ PciHostBridge.c
+ PciRootBridgeIo.c
+ PciHostBridge.h
+
+[Protocols]
+ gEfiPciHostBridgeResourceAllocationProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiMetronomeArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEmbeddedGpioProtocolGuid
+
+[depex]
+ gEfiMetronomeArchProtocolGuid
+
+[FeaturePcd]
+
+[Pcd]
+
+[FixedPcd]
+ gHisiTokenSpaceGuid.PcdPcieRootBridgeMask
+ gHisiTokenSpaceGuid.PcdPcieRootBridgeMask2P
+ gHisiTokenSpaceGuid.Pcdsoctype
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## PRODUCES ## Event
diff --git a/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000000..03edcf1e17
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -0,0 +1,2313 @@
+/**
+ * Copyright (c) 2014, AppliedMicro Corp. All rights reserved.
+ * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+ * Copyright (c) 2016, Linaro Limited. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ *
+ **/
+
+#include "PciHostBridge.h"
+#include <Library/DevicePathLib.h>
+#include <Library/DmaLib.h>
+#include <Library/PciExpressLib.h>
+#include <Regs/HisiPcieV1RegOffset.h>
+
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
+} RESOURCE_CONFIGURATION;
+
+RESOURCE_CONFIGURATION Configuration = {
+ {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
+ {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
+ {0x79, 0}
+};
+
+//
+// Protocol Member Function Prototypes
+//
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ OUT VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Memory Controller Pci Root Bridge Io Module Variables
+//
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mInStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 0, // EfiPciWidthFifoUint8
+ 0, // EfiPciWidthFifoUint16
+ 0, // EfiPciWidthFifoUint32
+ 0, // EfiPciWidthFifoUint64
+ 1, // EfiPciWidthFillUint8
+ 2, // EfiPciWidthFillUint16
+ 4, // EfiPciWidthFillUint32
+ 8 // EfiPciWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mOutStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 1, // EfiPciWidthFifoUint8
+ 2, // EfiPciWidthFifoUint16
+ 4, // EfiPciWidthFifoUint32
+ 8, // EfiPciWidthFifoUint64
+ 0, // EfiPciWidthFillUint8
+ 0, // EfiPciWidthFillUint16
+ 0, // EfiPciWidthFillUint32
+ 0 // EfiPciWidthFillUint64
+};
+
+
+UINT64 GetPcieCfgAddress (
+ UINT64 Ecam,
+ UINTN Bus,
+ UINTN Device,
+ UINTN Function,
+ UINTN Reg
+ )
+{
+ return Ecam + PCI_EXPRESS_LIB_ADDRESS (Bus, Device, Function, Reg);
+}
+
+
+void SetAtuConfig0RW (
+ PCI_ROOT_BRIDGE_INSTANCE *Private,
+ UINT32 Index
+ )
+{
+ UINTN RbPciBase = Private->RbPciBar;
+ UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusBase + 1, 1, 0, 0) - 1;
+
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG0);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE);
+
+ {
+ UINTN i;
+ for (i=0; i<0x20; i+=4) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
+ }
+ }
+}
+
+void SetAtuConfig1RW (
+ PCI_ROOT_BRIDGE_INSTANCE *Private,
+ UINT32 Index
+ )
+{
+ UINTN RbPciBase = Private->RbPciBar;
+ UINT64 MemLimit = GetPcieCfgAddress (Private->Ecam, Private->BusLimit + 1, 0, 0, 0) - 1;
+
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_CONFIG1);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(Private->Ecam));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(Private->Ecam) >> 32));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32) MemLimit);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, 0);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, 0);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_SHIIF_MODE);
+
+ {
+ UINTN i;
+ for (i=0; i<0x20; i+=4) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
+ }
+ }
+}
+
+void SetAtuIoRW(UINT64 RbPciBase,UINT64 IoBase,UINT64 CpuIoRegionLimit, UINT64 CpuIoRegionBase, UINT32 Index)
+{
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_IO);
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuIoRegionBase));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)CpuIoRegionBase >> 32));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuIoRegionLimit));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(IoBase));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(IoBase) >> 32));
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE);
+
+ {
+ UINTN i;
+ for (i=0; i<0x20; i+=4) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
+ }
+ }
+}
+
+void SetAtuMemRW(UINT64 RbPciBase,UINT64 MemBase,UINT64 CpuMemRegionLimit, UINT64 CpuMemRegionBase, UINT32 Index)
+{
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_VIEW_POINT, Index);
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL1, IATU_CTRL1_TYPE_MEM);
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LOW, (UINT32)(CpuMemRegionBase));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_HIGH, (UINT32)((UINT64)(CpuMemRegionBase) >> 32));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_BASE_LIMIT, (UINT32)(CpuMemRegionLimit));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_LOW, (UINT32)(MemBase));
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_TARGET_HIGH, (UINT32)((UINT64)(MemBase) >> 32));
+
+ MmioWrite32 (RbPciBase + IATU_OFFSET + IATU_REGION_CTRL2, IATU_NORMAL_MODE);
+
+ {
+ UINTN i;
+ for (i=0; i<0x20; i+=4) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] - Base=%p value=%x\n", __FUNCTION__, __LINE__, RbPciBase + 0x900 + i, MmioRead32(RbPciBase + 0x900 + i)));
+ }
+ }
+}
+
+VOID InitAtu (PCI_ROOT_BRIDGE_INSTANCE *Private)
+{
+ SetAtuMemRW (Private->RbPciBar, Private->PciRegionBase, Private->PciRegionLimit, Private->CpuMemRegionBase, 0);
+ SetAtuConfig0RW (Private, 1);
+ SetAtuConfig1RW (Private, 2);
+ SetAtuIoRW (Private->RbPciBar, Private->IoBase, Private->IoLimit, Private->CpuIoRegionBase, 3);
+}
+
+
+BOOLEAN PcieIsLinkUp (UINT32 SocType, UINTN RbPciBar, UINTN Port)
+{
+ UINT32 Value = 0;
+
+ if (0x1610 == SocType)
+ {
+ Value = MmioRead32(RbPciBar + 0x131C);
+ if ((Value & 0x3F) == 0x11)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ else
+ {
+ Value = MmioRead32 (0xb0000000 + 0x6818 + 0x100 * Port);
+ if ((Value & 0x3F) == 0x11)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+}
+
+/**
+
+ Construct the Pci Root Bridge Io protocol
+
+ @param Protocol Point to protocol instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param ResAppeture ResourceAppeture for host bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture,
+ IN UINT32 Seg
+ )
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_RESOURCE_TYPE Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
+
+ //
+ // The host to pci bridge, the host memory and io addresses are
+ // direct mapped to pci addresses, so no need translate, set bases to 0.
+ //
+ PrivateData->MemBase = ResAppeture->MemBase;
+ PrivateData->IoBase = ResAppeture->IoBase;
+ PrivateData->RbPciBar = ResAppeture->RbPciBar;
+ PrivateData->MemLimit = ResAppeture->MemLimit;
+ PrivateData->IoLimit = ResAppeture->IoLimit;
+ PrivateData->Ecam = ResAppeture->Ecam;
+ PrivateData->CpuMemRegionBase = ResAppeture->CpuMemRegionBase;
+ PrivateData->CpuIoRegionBase = ResAppeture->CpuIoRegionBase;
+ PrivateData->PciRegionBase = ResAppeture->PciRegionBase;
+ PrivateData->PciRegionLimit = ResAppeture->PciRegionLimit;
+
+ //
+ // Bus Appeture for this Root Bridge (Possible Range)
+ //
+ PrivateData->BusBase = ResAppeture->BusBase;
+ PrivateData->BusLimit = ResAppeture->BusLimit;
+
+ //
+ // Specific for this chipset
+ //
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ PrivateData->ResAllocNode[Index].Type = Index;
+ PrivateData->ResAllocNode[Index].Base = 0;
+ PrivateData->ResAllocNode[Index].Length = 0;
+ PrivateData->ResAllocNode[Index].Status = ResNone;
+ }
+
+ PrivateData->RootBridgeAttrib = Attri;
+
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | \
+ EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER;
+ PrivateData->Attributes = PrivateData->Supports;
+
+ Protocol->ParentHandle = HostBridgeHandle;
+
+ Protocol->PollMem = RootBridgeIoPollMem;
+ Protocol->PollIo = RootBridgeIoPollIo;
+
+ Protocol->Mem.Read = RootBridgeIoMemRead;
+ Protocol->Mem.Write = RootBridgeIoMemWrite;
+
+ Protocol->Io.Read = RootBridgeIoIoRead;
+ Protocol->Io.Write = RootBridgeIoIoWrite;
+
+ Protocol->CopyMem = RootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = RootBridgeIoPciRead;
+ Protocol->Pci.Write = RootBridgeIoPciWrite;
+
+ Protocol->Map = RootBridgeIoMap;
+ Protocol->Unmap = RootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
+
+ Protocol->Flush = RootBridgeIoFlush;
+
+ Protocol->GetAttributes = RootBridgeIoGetAttributes;
+ Protocol->SetAttributes = RootBridgeIoSetAttributes;
+
+ Protocol->Configuration = RootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = Seg;
+
+ InitAtu (PrivateData);
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR,"LocateProtocol MetronomeArchProtocol Error\n"));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
+
+ The I/O operations are carried out exactly as requested. The caller is responsible
+ for satisfying any alignment and I/O width restrictions that a PI System on a
+ platform might require. For example on some platforms, width requests of
+ EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
+ be handled by the driver.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] OperationType I/O operation type: IO/MMIO/PCI.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The parameters for this request pass the checks.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+RootBridgeIoCheckParameter (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN OPERATION_TYPE OperationType,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
+ UINT64 MaxCount;
+ UINT64 Base;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if ((UINT32)Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For FIFO type, the target address won't increase during the access,
+ // so treat Count as 1
+ //
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Address is aligned
+ //
+ if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > Limit + 1
+ //
+ // Since Limit can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all oveflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
+ // Limit is of the form (2^n - 1).
+ //
+ if (OperationType == IoOperation) {
+ Base = PrivateData->IoBase;
+ Limit = PrivateData->IoLimit;
+ } else if (OperationType == MemOperation) {
+ Base = PrivateData->MemBase;
+ Limit = PrivateData->MemLimit;
+ } else {
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
+ if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* The root complex has only one device / function */
+ if (PciRbAddr->Bus == PrivateData->BusBase && PciRbAddr->Device != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* The other side of the RC has only one device as well */
+ if (PciRbAddr->Bus == (PrivateData->BusBase + 1 ) && PciRbAddr->Device != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciRbAddr->ExtendedRegister != 0) {
+ Address = PciRbAddr->ExtendedRegister;
+ } else {
+ Address = PciRbAddr->Register;
+ }
+ Base = 0;
+ Limit = MAX_PCI_REG_ADDRESS;
+ }
+
+ if (Address < Base) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Count == 0) {
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ MaxCount = RShiftU64 (Limit, Width);
+ if (MaxCount < (Count - 1)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write memory space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ /* Address is bus resource */
+ Address -= PrivateData->PciRegionBase;
+ Address += PrivateData->CpuMemRegionBase;
+
+ PCIE_DEBUG("RootBridgeIoMemRW Address:0x%llx\n", Address);
+ PCIE_DEBUG("RootBridgeIoMemRW Count:0x%llx\n", Count);
+ PCIE_DEBUG("RootBridgeIoMemRW Write:0x%llx\n", Write);
+ PCIE_DEBUG("RootBridgeIoMemRW Width:0x%llx\n", Width);
+
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint64:
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint64:
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write IO space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoIoRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ /* Address is bus resource */
+ Address -= PrivateData->IoBase;
+ Address += PrivateData->CpuIoRegionBase;
+
+ Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint64:
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (OperationWidth) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint64:
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+
+ } else {
+
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
+ // protocol definition is updated.
+ //
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks != 0) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ //
+ // No matter what, always do a single poll.
+ //
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+
+ } else {
+
+ //
+ // Determine the proper # of metronome ticks to wait for polling the
+ // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // The "+1" to account for the possibility of the first tick being short
+ // because we started in the middle of a tick.
+ //
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks != 0) {
+
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if ((UINT32)Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)((UINTN)1 << Width);
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count-1) * Stride;
+ DestAddress = DestAddress + (Count-1) * Stride;
+ }
+
+ for (Index = 0;Index < Count;Index++) {
+ Status = RootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads memory-mapped registers.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+CpuMemoryServiceRead (
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+ UINT32 Uint32Buffer = 0;
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3)));
+ Uint32Buffer &= (0xFF << ((Address & 0x3) * 8));
+ *((UINT8*)Uint8Buffer) = (UINT8)(Uint32Buffer >> (((Address & 0x3) * 8)));
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Uint32Buffer = MmioRead32((UINTN)(Address & (~0x3)));
+ Uint32Buffer &= (0xFFFF << ((Address & 0x3) * 8));
+ *(UINT16 *)Uint8Buffer = (UINT16)(Uint32Buffer >> (((Address & 0x3) * 8)));
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 EfiAddress,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ UINT32 Offset;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
+ UINT64 Address;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EfiPciAddress->ExtendedRegister) {
+ Offset = EfiPciAddress->ExtendedRegister;
+ } else {
+ Offset = EfiPciAddress->Register;
+ }
+
+ PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ if (EfiPciAddress->Bus < PrivateData->BusBase || EfiPciAddress->Bus > PrivateData->BusLimit) {
+ PCIE_DEBUG ("[%a:%d] - Bus number out of range %d\n", __FUNCTION__, __LINE__, EfiPciAddress->Bus);
+ SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The UEFI PCI enumerator scans for devices at all possible addresses,
+ // and ignores some PCI rules - this results in some hardware being
+ // detected multiple times. We work around this by faking absent
+ // devices
+ if(EfiPciAddress->Bus == PrivateData->BusBase)
+ {
+ if((EfiPciAddress->Device != 0x0) || (EfiPciAddress->Function != 0)) {
+ SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (EfiPciAddress->Bus == PrivateData->BusBase){
+ Address = PrivateData->RbPciBar + Offset;
+ }
+ else if(EfiPciAddress->Bus == PrivateData->BusBase + 1)
+ {
+ if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port))
+ {
+ SetMem (Buffer, mOutStride[Width] * Count, 0xFF);
+ return EFI_NOT_READY;
+ }
+ Address = GetPcieCfgAddress (
+ PrivateData->Ecam,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ }
+ else
+ {
+ Address = GetPcieCfgAddress (
+ PrivateData->Ecam,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ }
+
+ (VOID)CpuMemoryServiceRead((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+ PCIE_DEBUG ("[%a:%d] - %x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes memory-mapped registers.
+ @param[in] Width Signifies the width of the I/O or Memory operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Count The number of I/O operations to perform. The number of
+ bytes moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results.
+ For write operations, the source buffer from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the PI system.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+ and Count is not valid for this PI system.
+
+**/
+EFI_STATUS
+CpuMemoryServiceWrite (
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT8 InStride;
+ UINT8 OutStride;
+ EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
+ UINT8 *Uint8Buffer;
+ UINT32 Uint32Buffer;
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+ OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (OperationWidth == EfiCpuIoWidthUint8) {
+ Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03)));
+ Uint32Buffer &= ~(UINT32)(0xFF << ((Address & 0x3) * 8));
+ Uint32Buffer |= (UINT32)(*(UINT8 *)Uint8Buffer) << ((Address & 0x3) * 8);
+ MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer);
+ } else if (OperationWidth == EfiCpuIoWidthUint16) {
+ if (((Address & 0x3) == 1) || ((Address & 0x3) == 3)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Uint32Buffer = MmioRead32 ((UINTN)(Address & (~0x03)));
+ Uint32Buffer &= ~(UINT32)(0xFFFF << ((Address & 0x3) * 8));
+ Uint32Buffer |= (UINT32)(*(UINT16 *)Uint8Buffer) << ((Address & 0x3) * 8);
+ MmioWrite32 ((UINTN)(Address & (~0x03)), Uint32Buffer);
+ } else if (OperationWidth == EfiCpuIoWidthUint32) {
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else if (OperationWidth == EfiCpuIoWidthUint64) {
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 EfiAddress,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT32 Offset;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
+ UINT64 Address;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EfiPciAddress->ExtendedRegister)
+ Offset = EfiPciAddress->ExtendedRegister;
+ else
+ Offset = EfiPciAddress->Register;
+
+ PCIE_DEBUG ("[%a:%d] - bus %x dev %x func %x Off %x\n", __FUNCTION__, __LINE__,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ if (((EfiPciAddress->Bus == PrivateData->BusBase) && (EfiPciAddress->Device == 0x00) && (EfiPciAddress->Function == 0))){
+ Address = PrivateData->RbPciBar + Offset;
+ if ((Offset == 0x14) || (Offset == 0x10)) {
+ return EFI_SUCCESS;
+ }
+ }
+ else if (EfiPciAddress->Bus == PrivateData->BusBase + 1)
+ {
+ if (!PcieIsLinkUp(PrivateData->SocType,PrivateData->RbPciBar, PrivateData->Port)) {
+ return EFI_NOT_READY;
+ }
+ Address = GetPcieCfgAddress (
+ PrivateData->Ecam,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ }
+ else
+ {
+ Address = GetPcieCfgAddress (
+ PrivateData->Ecam,
+ EfiPciAddress->Bus,
+ EfiPciAddress->Device,
+ EfiPciAddress->Function,
+ Offset
+ );
+ }
+
+ (VOID)CpuMemoryServiceWrite ((EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+ PCIE_DEBUG ("[%a:%d] - 0x%08x\n", __FUNCTION__, __LINE__, *(UINT32 *)Buffer);
+ return EFI_SUCCESS;
+}
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ DMA_MAP_OPERATION DmaOperation;
+
+ if (Operation == EfiPciOperationBusMasterRead) {
+ DmaOperation = MapOperationBusMasterRead;
+ } else if (Operation == EfiPciOperationBusMasterWrite) {
+ DmaOperation = MapOperationBusMasterWrite;
+ } else if (Operation == EfiPciOperationBusMasterCommonBuffer) {
+ DmaOperation = MapOperationBusMasterCommonBuffer;
+ } else if (Operation == EfiPciOperationBusMasterRead64) {
+ DmaOperation = MapOperationBusMasterRead;
+ } else if (Operation == EfiPciOperationBusMasterWrite64) {
+ DmaOperation = MapOperationBusMasterWrite;
+ } else if (Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ DmaOperation = MapOperationBusMasterCommonBuffer;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ (VOID)DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+ return EFI_SUCCESS;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ return DmaUnmap (Mapping);
+}
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
+
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+{
+ return DmaFreeBuffer (Pages, HostAddress);
+}
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+{
+ //
+ // not supported yet
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set the return value for Supported and Attributes
+ //
+ if (Supported != NULL) {
+ *Supported = PrivateData->Supports;
+ }
+
+ if (Attributes != NULL) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes != 0) {
+ if ((Attributes & (~(PrivateData->Supports))) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ if (Attributes & (~PrivateData->Attributes)) {
+ /* FIXME: */
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ for (Index = 0; Index < TypeMax; Index++) {
+ if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
+ Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+ Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
+ Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
+ }
+ }
+
+ *Resources = &Configuration;
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c
new file mode 100644
index 0000000000..18085c43c5
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.c
@@ -0,0 +1,1049 @@
+/** @file
+
+ Copyright (c) 2016 Linaro Ltd.
+ Copyright (c) 2016 Hisilicon Limited.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DmaLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+
+#include <Protocol/PlatformSasProtocol.h>
+#include <Protocol/ScsiPassThruExt.h>
+#include <IndustryStandard/Scsi.h>
+
+#define READ_REG32(Base, Offset) MmioRead32 ((Base) + (Offset))
+#define WRITE_REG32(Base, Offset, Val) MmioWrite32 ((Base) + (Offset), (Val))
+
+#define PHY_READ_REG32(Base, Offset, phy) MmioRead32 ((Base) + (Offset) + 0x400 * (phy))
+#define PHY_WRITE_REG32(Base, Offset, phy, Val) MmioWrite32 ((Base) + (Offset) + 0x400 * (phy), (Val))
+
+#define DLVRY_QUEUE_ENABLE 0x0
+#define IOST_BASE_ADDR_LO 0x8
+#define IOST_BASE_ADDR_HI 0xc
+#define ITCT_BASE_ADDR_LO 0x10
+#define ITCT_BASE_ADDR_HI 0x14
+#define BROKEN_MSG_ADDR_LO 0x18
+#define BROKEN_MSG_ADDR_HI 0x1c
+#define PHY_CONTEXT 0x20
+#define PHY_PORT_NUM_MA 0x28
+#define HGC_TRANS_TASK_CNT_LIMIT 0x38
+#define AXI_AHB_CLK_CFG 0x3c
+#define HGC_SAS_TXFAIL_RETRY_CTRL 0x84
+#define HGC_GET_ITV_TIME 0x90
+#define DEVICE_MSG_WORK_MODE 0x94
+#define I_T_NEXUS_LOSS_TIME 0xa0
+#define BUS_INACTIVE_LIMIT_TIME 0xa8
+#define REJECT_TO_OPEN_LIMIT_TIME 0xac
+#define CFG_AGING_TIME 0xbc
+#define HGC_DFX_CFG2 0xc0
+#define FIS_LIST_BADDR_L 0xc4
+#define CFG_1US_TIMER_TRSH 0xcc
+#define CFG_SAS_CONFIG 0xd4
+#define INT_COAL_EN 0x1bc
+#define OQ_INT_COAL_TIME 0x1c0
+#define OQ_INT_COAL_CNT 0x1c4
+#define ENT_INT_COAL_TIME 0x1c8
+#define ENT_INT_COAL_CNT 0x1cc
+#define OQ_INT_SRC 0x1d0
+#define OQ_INT_SRC_MSK 0x1d4
+#define ENT_INT_SRC1 0x1d8
+#define ENT_INT_SRC2 0x1dc
+#define ENT_INT_SRC_MSK1 0x1e0
+#define ENT_INT_SRC_MSK2 0x1e4
+#define SAS_ECC_INTR_MSK 0x1ec
+#define HGC_ERR_STAT_EN 0x238
+#define DLVRY_Q_0_BASE_ADDR_LO 0x260
+#define DLVRY_Q_0_BASE_ADDR_HI 0x264
+#define DLVRY_Q_0_DEPTH 0x268
+#define DLVRY_Q_0_WR_PTR 0x26c
+#define DLVRY_Q_0_RD_PTR 0x270
+#define COMPL_Q_0_BASE_ADDR_LO 0x4e0
+#define COMPL_Q_0_BASE_ADDR_HI 0x4e4
+#define COMPL_Q_0_DEPTH 0x4e8
+#define COMPL_Q_0_WR_PTR 0x4ec
+#define COMPL_Q_0_RD_PTR 0x4f0
+#define AXI_CFG 0x5100
+
+#define PORT_BASE 0x800
+#define PHY_CFG (PORT_BASE + 0x0)
+#define PHY_CFG_ENA_OFF 0
+#define PHY_CFG_ENA_MSK (0x1 << PHY_CFG_ENA_OFF)
+#define PHY_CFG_DC_OPT_OFF 2
+#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
+#define PROG_PHY_LINK_RATE (PORT_BASE + 0xc)
+#define PHY_CTRL (PORT_BASE + 0x14)
+#define PHY_CTRL_RESET BIT0
+#define PHY_RATE_NEGO (PORT_BASE + 0x30)
+#define PHY_PCN (PORT_BASE + 0x44)
+#define SL_TOUT_CFG (PORT_BASE + 0x8c)
+#define SL_CONTROL (PORT_BASE + 0x94)
+#define SL_CONTROL_NOTIFY_EN BIT0
+#define TX_ID_DWORD0 (PORT_BASE + 0x9c)
+#define TX_ID_DWORD1 (PORT_BASE + 0xa0)
+#define TX_ID_DWORD2 (PORT_BASE + 0xa4)
+#define TX_ID_DWORD3 (PORT_BASE + 0xa8)
+#define TX_ID_DWORD4 (PORT_BASE + 0xaC)
+#define TX_ID_DWORD5 (PORT_BASE + 0xb0)
+#define TX_ID_DWORD6 (PORT_BASE + 0xb4)
+#define RX_IDAF_DWORD3 (PORT_BASE + 0xd0)
+#define RX_IDAF_DWORD4 (PORT_BASE + 0xd4)
+#define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
+#define DONE_RECEIVED_TIME (PORT_BASE + 0x12c)
+#define CON_CFG_DRIVER (PORT_BASE + 0x130)
+#define PHY_CONFIG2 (PORT_BASE + 0x1a8)
+#define PHY_CONFIG2_FORCE_TXDEEMPH_OFF 3
+#define PHY_CONFIG2_FORCE_TXDEEMPH_MSK (0x1 << PHY_CONFIG2_FORCE_TXDEEMPH_OFF)
+#define CHL_INT_COAL_EN (PORT_BASE + 0x1d0)
+#define CHL_INT0 (PORT_BASE + 0x1b0)
+#define CHL_INT0_PHYCTRL_NOTRDY BIT0
+#define CHL_INT1 (PORT_BASE + 0x1b4)
+#define CHL_INT2 (PORT_BASE + 0x1b8)
+#define CHL_INT2_SL_PHY_ENA BIT6
+#define CHL_INT0_MSK (PORT_BASE + 0x1bc)
+#define CHL_INT0_MSK_PHYCTRL_NOTRDY BIT0
+#define CHL_INT1_MSK (PORT_BASE + 0x1c0)
+#define CHL_INT2_MSK (PORT_BASE + 0x1c4)
+#define DMA_TX_STATUS (PORT_BASE + 0x2d0)
+#define DMA_TX_STATUS_BUSY BIT0
+#define DMA_RX_STATUS (PORT_BASE + 0x2e8)
+#define DMA_RX_STATUS_BUSY BIT0
+
+#define QUEUE_CNT 32
+#define QUEUE_SLOTS 256
+#define SLOT_ENTRIES 8192
+#define PHY_CNT 8
+#define MAX_ITCT_ENTRIES 1
+
+// Completion header
+#define CMPLT_HDR_IPTT_OFF 0
+#define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF)
+
+#define BIT(x) (1 << x)
+
+// HW dma structures
+// Delivery queue header
+// dw0
+#define CMD_HDR_RESP_REPORT_OFF 5
+#define CMD_HDR_RESP_REPORT_MSK 0x20
+#define CMD_HDR_TLR_CTRL_OFF 6
+#define CMD_HDR_TLR_CTRL_MSK 0xc0
+#define CMD_HDR_PORT_OFF 17
+#define CMD_HDR_PORT_MSK 0xe0000
+#define CMD_HDR_PRIORITY_OFF 27
+#define CMD_HDR_PRIORITY_MSK 0x8000000
+#define CMD_HDR_MODE_OFF 28
+#define CMD_HDR_MODE_MSK 0x10000000
+#define CMD_HDR_CMD_OFF 29
+#define CMD_HDR_CMD_MSK 0xe0000000
+// dw1
+#define CMD_HDR_VERIFY_DTL_OFF 10
+#define CMD_HDR_VERIFY_DTL_MSK 0x400
+#define CMD_HDR_SSP_FRAME_TYPE_OFF 13
+#define CMD_HDR_SSP_FRAME_TYPE_MSK 0xe000
+#define CMD_HDR_DEVICE_ID_OFF 16
+#define CMD_HDR_DEVICE_ID_MSK 0xffff0000
+// dw2
+#define CMD_HDR_CFL_OFF 0
+#define CMD_HDR_CFL_MSK 0x1ff
+#define CMD_HDR_MRFL_OFF 15
+#define CMD_HDR_MRFL_MSK 0xff8000
+#define CMD_HDR_FIRST_BURST_OFF 25
+#define CMD_HDR_FIRST_BURST_MSK 0x2000000
+// dw3
+#define CMD_HDR_IPTT_OFF 0
+#define CMD_HDR_IPTT_MSK 0xffff
+// dw6
+#define CMD_HDR_DATA_SGL_LEN_OFF 16
+#define CMD_HDR_DATA_SGL_LEN_MSK 0xffff0000
+
+// Completion header
+#define CMPLT_HDR_IPTT_OFF 0
+#define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF)
+#define CMPLT_HDR_CMD_CMPLT_MSK BIT17
+#define CMPLT_HDR_ERR_RCRD_XFRD_MSK BIT18
+#define CMPLT_HDR_RSPNS_XFRD_MSK BIT19
+#define CMPLT_HDR_IO_CFG_ERR_MSK BIT27
+
+#define SENSE_DATA_PRES 26
+
+#define SGE_LIMIT 0x10000
+#define upper_32_bits(n) ((UINT32)(((n) >> 16) >> 16))
+#define lower_32_bits(n) ((UINT32)(n))
+#define MAX_TARGET_ID 4
+
+// Generic HW DMA host memory structures
+struct hisi_sas_cmd_hdr {
+ UINT32 dw0;
+ UINT32 dw1;
+ UINT32 dw2;
+ UINT32 transfer_tags;
+ UINT32 data_transfer_len;
+ UINT32 first_burst_num;
+ UINT32 sg_len;
+ UINT32 dw7;
+ UINT64 cmd_table_addr;
+ UINT64 sts_buffer_addr;
+ UINT64 prd_table_addr;
+ UINT64 dif_prd_table_addr;
+};
+
+struct hisi_sas_complete_hdr {
+ UINT32 data;
+};
+
+struct hisi_sas_iost {
+ UINT64 qw0;
+ UINT64 qw1;
+ UINT64 qw2;
+ UINT64 qw3;
+};
+
+struct hisi_sas_itct {
+ UINT64 qw0;
+ UINT64 sas_addr;
+ UINT64 qw2;
+ UINT64 qw3;
+ UINT64 qw4;
+ UINT64 qw_sata_ncq0_3;
+ UINT64 qw_sata_ncq7_4;
+ UINT64 qw_sata_ncq11_8;
+ UINT64 qw_sata_ncq15_12;
+ UINT64 qw_sata_ncq19_16;
+ UINT64 qw_sata_ncq23_20;
+ UINT64 qw_sata_ncq27_24;
+ UINT64 qw_sata_ncq31_28;
+ UINT64 qw_non_ncq_iptt;
+ UINT64 qw_rsvd0;
+ UINT64 qw_rsvd1;
+};
+
+struct hisi_sas_breakpoint {
+ UINT8 data[128];
+};
+
+struct hisi_sas_sge {
+ UINT64 addr;
+ UINT32 page_ctrl_0;
+ UINT32 page_ctrl_1;
+ UINT32 data_len;
+ UINT32 data_off;
+};
+
+struct hisi_sas_sge_page {
+ struct hisi_sas_sge sg[512];
+};
+
+struct hisi_sas_cmd {
+ UINT8 cmd[128];
+};
+
+struct hisi_sas_sts {
+UINT32 status[260];
+};
+
+struct hisi_sas_slot {
+ BOOLEAN used;
+};
+
+struct hisi_hba {
+ struct hisi_sas_cmd_hdr *cmd_hdr[QUEUE_CNT];
+ struct hisi_sas_complete_hdr *complete_hdr[QUEUE_CNT];
+ struct hisi_sas_sge_page *sge[QUEUE_CNT];
+ struct hisi_sas_sts *status_buf[QUEUE_CNT];
+ struct hisi_sas_cmd *command_table[QUEUE_CNT];
+ struct hisi_sas_iost *iost;
+ struct hisi_sas_itct *itct;
+ struct hisi_sas_breakpoint *breakpoint;
+ struct hisi_sas_slot *slots;
+ UINT32 base;
+ int queue;
+ int port_id;
+ UINT32 LatestTargetId;
+ UINT64 LatestLun;
+};
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT64 PhysBase;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SAS_V1_TRANSPORT_DEVICE_PATH;
+#pragma pack ()
+
+typedef struct {
+ UINT32 Signature;
+ EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;
+ SAS_V1_TRANSPORT_DEVICE_PATH *DevicePath;
+ struct hisi_hba *hba;
+ EFI_EVENT TimerEvent;
+} SAS_V1_INFO;
+
+#define SAS_DEVICE_SIGNATURE SIGNATURE_32 ('S','A','S','0')
+#define SAS_FROM_PASS_THRU(a) CR (a, SAS_V1_INFO, ExtScsiPassThru, SAS_DEVICE_SIGNATURE)
+
+STATIC EFI_STATUS prepare_cmd (
+ struct hisi_hba *hba,
+ EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ struct hisi_sas_slot *slot;
+ struct hisi_sas_cmd_hdr *hdr;
+ struct hisi_sas_sge_page *sge;
+ struct hisi_sas_sts *sts;
+ struct hisi_sas_cmd *cmd;
+ EFI_SCSI_SENSE_DATA *SensePtr = Packet->SenseData;
+ VOID *Buffer = NULL;
+ UINTN BufferSize = 0;
+ int queue = hba->queue;
+ UINT32 r, w = 0, slot_idx = 0;
+ UINT32 base = hba->base;
+ UINT8 *p;
+ EFI_PHYSICAL_ADDRESS BufferAddress;
+ EFI_STATUS Status = EFI_SUCCESS;
+ VOID *BufferMap = NULL;
+ DMA_MAP_OPERATION DmaOperation = MapOperationBusMasterCommonBuffer;
+
+ while (1) {
+ w = READ_REG32(base, DLVRY_Q_0_WR_PTR + (queue * 0x14));
+ r = READ_REG32(base, DLVRY_Q_0_RD_PTR + (queue * 0x14));
+ slot_idx = queue * QUEUE_SLOTS + w;
+ slot = &hba->slots[slot_idx];
+ if (slot->used || (r == (w+1) % QUEUE_SLOTS)) {
+ queue = (queue + 1) % QUEUE_CNT;
+ if (queue == hba->queue) {
+ DEBUG ((EFI_D_ERROR, "could not find free slot\n"));
+ return EFI_NOT_READY;
+ }
+ continue;
+ }
+ break;
+ }
+
+ hdr = &hba->cmd_hdr[queue][w];
+ cmd = &hba->command_table[queue][w];
+ sts = &hba->status_buf[queue][w];
+ sge = &hba->sge[queue][w];
+
+ ZeroMem (cmd, sizeof (struct hisi_sas_cmd));
+ ZeroMem (sts, sizeof (struct hisi_sas_sts));
+ if (SensePtr)
+ ZeroMem (SensePtr, sizeof (EFI_SCSI_SENSE_DATA));
+
+ slot->used = TRUE;
+ hba->queue = (queue + 1) % QUEUE_CNT;
+
+ // Only consider ssp
+ hdr->dw0 = (1 << CMD_HDR_RESP_REPORT_OFF) |
+ (0x2 << CMD_HDR_TLR_CTRL_OFF) |
+ (hba->port_id << CMD_HDR_PORT_OFF) |
+ (1 << CMD_HDR_MODE_OFF) |
+ (1 << CMD_HDR_CMD_OFF);
+ hdr->dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF;
+ hdr->dw1 |= 0 << CMD_HDR_DEVICE_ID_OFF;
+ hdr->dw2 = 0x83000d;
+ hdr->transfer_tags = slot_idx << CMD_HDR_IPTT_OFF;
+
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+ Buffer = Packet->InDataBuffer;
+ BufferSize = Packet->InTransferLength;
+ if (Buffer) {
+ hdr->dw1 |= 1 << CMD_HDR_SSP_FRAME_TYPE_OFF;
+ DmaOperation = MapOperationBusMasterWrite;
+ }
+ } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) {
+ Buffer = Packet->OutDataBuffer;
+ BufferSize = Packet->OutTransferLength;
+ if (Buffer) {
+ DmaOperation = MapOperationBusMasterRead;
+ hdr->dw1 |= 2 << CMD_HDR_SSP_FRAME_TYPE_OFF;
+ }
+ } else {
+ hdr->dw1 |= 0 << CMD_HDR_SSP_FRAME_TYPE_OFF;
+ }
+
+ hdr->data_transfer_len = BufferSize;
+ hdr->cmd_table_addr = (UINT64)cmd;
+ hdr->sts_buffer_addr = (UINT64)sts;
+
+ CopyMem (&cmd->cmd[36], Packet->Cdb, Packet->CdbLength);
+
+ if (Buffer != NULL) {
+ struct hisi_sas_sge *sg;
+ UINT32 remain, len, pos = 0, i = 0;
+
+ Status = DmaMap (DmaOperation, Buffer, &BufferSize, &BufferAddress, &BufferMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ remain = len = BufferSize;
+
+ while (remain) {
+ if (len > SGE_LIMIT)
+ len = SGE_LIMIT;
+ sg = &sge->sg[i];
+ sg->addr = (UINT64)(BufferAddress + pos);
+ sg->page_ctrl_0 = sg->page_ctrl_1 = 0;
+ sg->data_len = len;
+ sg->data_off = 0;
+ remain -= len;
+ pos += len;
+ len = remain;
+ i++;
+ }
+
+ hdr->prd_table_addr = (UINT64)sge;
+ hdr->sg_len = i << CMD_HDR_DATA_SGL_LEN_OFF;
+ }
+
+ // Ensure descriptor effective before start dma
+ MemoryFence();
+
+ // Start dma
+ WRITE_REG32(base, DLVRY_Q_0_WR_PTR + queue * 0x14, ++w % QUEUE_SLOTS);
+
+ // Wait for dma complete
+ while (slot->used) {
+ if (READ_REG32(base, OQ_INT_SRC) & BIT(queue)) {
+ struct hisi_sas_complete_hdr *complete_hdr;
+ UINT32 data, rd;
+ rd = READ_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue));
+
+ complete_hdr = &hba->complete_hdr[queue][rd];
+ data = complete_hdr->data;
+
+ // Check whether dma transfer error
+ if ((data & CMPLT_HDR_ERR_RCRD_XFRD_MSK) &&
+ !(data & CMPLT_HDR_RSPNS_XFRD_MSK)) {
+ DEBUG ((EFI_D_VERBOSE, "sas retry data=0x%x\n", data));
+ DEBUG ((EFI_D_VERBOSE, "sts[0]=0x%x\n", sts->status[0]));
+ DEBUG ((EFI_D_VERBOSE, "sts[1]=0x%x\n", sts->status[1]));
+ DEBUG ((EFI_D_VERBOSE, "sts[2]=0x%x\n", sts->status[2]));
+ Status = EFI_NOT_READY;
+ // wait 1 second and retry, some disk need long time to be ready
+ // and ScsiDisk treat retry over 3 times as error
+ MicroSecondDelay(1000000);
+ }
+ // Update read point
+ WRITE_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue), w);
+ // Clear int
+ WRITE_REG32(base, OQ_INT_SRC, BIT(queue));
+ slot->used = FALSE;
+ break;
+ }
+ // Wait for status change in polling
+ NanoSecondDelay (100);
+ }
+
+ if (BufferMap)
+ DmaUnmap (BufferMap);
+
+ p = (UINT8 *)&sts->status[0];
+ if (p[SENSE_DATA_PRES]) {
+ // Disk not ready normal return for ScsiDiskTestUnitReady do next try
+ SensePtr->Sense_Key = EFI_SCSI_SK_NOT_READY;
+ SensePtr->Addnl_Sense_Code = EFI_SCSI_ASC_NOT_READY;
+ SensePtr->Addnl_Sense_Code_Qualifier = EFI_SCSI_ASCQ_IN_PROGRESS;
+ // wait 1 second for disk spin up, refer drivers/scsi/sd.c
+ MicroSecondDelay(1000000);
+ }
+ return Status;
+}
+
+STATIC VOID hisi_sas_v1_init(struct hisi_hba *hba, PLATFORM_SAS_PROTOCOL *plat)
+{
+ int i, j;
+ UINT32 val, base = hba->base;
+
+ // Reset
+ for (i = 0; i < PHY_CNT; i++) {
+ UINT32 phy_ctrl = PHY_READ_REG32(base, PHY_CTRL, i);
+
+ phy_ctrl |= PHY_CTRL_RESET;
+ PHY_WRITE_REG32(base, PHY_CTRL, i, phy_ctrl);
+ }
+ // spec says safe to wait 50us after reset
+ MicroSecondDelay(50);
+
+ // Ensure DMA tx & rx idle
+ for (i = 0; i < PHY_CNT; i++) {
+ UINT32 dma_tx_status, dma_rx_status;
+
+ for (j = 0; j < 100; j++) {
+ dma_tx_status = PHY_READ_REG32(base, DMA_TX_STATUS, i);
+ dma_rx_status = PHY_READ_REG32(base, DMA_RX_STATUS, i);
+
+ if (!(dma_tx_status & DMA_TX_STATUS_BUSY) &&
+ !(dma_rx_status & DMA_RX_STATUS_BUSY))
+ break;
+
+ // Wait for status change in polling
+ NanoSecondDelay (100);
+ }
+ }
+
+ // Ensure axi bus idle
+ for (j = 0; j < 100; j++) {
+ UINT32 axi_status = READ_REG32(base, AXI_CFG);
+ if (axi_status == 0)
+ break;
+
+ // Wait for status change in polling
+ NanoSecondDelay (100);
+ }
+
+ plat->Init(plat);
+
+ WRITE_REG32(base, DLVRY_QUEUE_ENABLE, 0xffffffff);
+ WRITE_REG32(base, HGC_TRANS_TASK_CNT_LIMIT, 0x11);
+ WRITE_REG32(base, DEVICE_MSG_WORK_MODE, 0x1);
+ WRITE_REG32(base, HGC_SAS_TXFAIL_RETRY_CTRL, 0x1ff);
+ WRITE_REG32(base, HGC_ERR_STAT_EN, 0x401);
+ WRITE_REG32(base, CFG_1US_TIMER_TRSH, 0x64);
+ WRITE_REG32(base, HGC_GET_ITV_TIME, 0x1);
+ WRITE_REG32(base, I_T_NEXUS_LOSS_TIME, 0x64);
+ WRITE_REG32(base, BUS_INACTIVE_LIMIT_TIME, 0x2710);
+ WRITE_REG32(base, REJECT_TO_OPEN_LIMIT_TIME, 0x1);
+ WRITE_REG32(base, CFG_AGING_TIME, 0x7a12);
+ WRITE_REG32(base, HGC_DFX_CFG2, 0x9c40);
+ WRITE_REG32(base, FIS_LIST_BADDR_L, 0x2);
+ WRITE_REG32(base, INT_COAL_EN, 0xc);
+ WRITE_REG32(base, OQ_INT_COAL_TIME, 0x186a0);
+ WRITE_REG32(base, OQ_INT_COAL_CNT, 1);
+ WRITE_REG32(base, ENT_INT_COAL_TIME, 0x1);
+ WRITE_REG32(base, ENT_INT_COAL_CNT, 0x1);
+ WRITE_REG32(base, OQ_INT_SRC, 0xffffffff);
+ WRITE_REG32(base, ENT_INT_SRC1, 0xffffffff);
+ WRITE_REG32(base, ENT_INT_SRC_MSK1, 0);
+ WRITE_REG32(base, ENT_INT_SRC2, 0xffffffff);
+ WRITE_REG32(base, ENT_INT_SRC_MSK2, 0);
+ WRITE_REG32(base, SAS_ECC_INTR_MSK, 0);
+ WRITE_REG32(base, AXI_AHB_CLK_CFG, 0x2);
+ WRITE_REG32(base, CFG_SAS_CONFIG, 0x22000000);
+
+ for (i = 0; i < PHY_CNT; i++) {
+ PHY_WRITE_REG32(base, PROG_PHY_LINK_RATE, i, 0x88a);
+ PHY_WRITE_REG32(base, PHY_CONFIG2, i, 0x7c080);
+ PHY_WRITE_REG32(base, PHY_RATE_NEGO, i, 0x415ee00);
+ PHY_WRITE_REG32(base, PHY_PCN, i, 0x80a80000);
+ PHY_WRITE_REG32(base, SL_TOUT_CFG, i, 0x7d7d7d7d);
+ PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0x0);
+ PHY_WRITE_REG32(base, RXOP_CHECK_CFG_H, i, 0x1000);
+ PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0);
+ PHY_WRITE_REG32(base, CON_CFG_DRIVER, i, 0x13f0a);
+ PHY_WRITE_REG32(base, CHL_INT_COAL_EN, i, 3);
+ PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 8);
+ }
+
+ for (i = 0; i < QUEUE_CNT; i++) {
+ WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->cmd_hdr[i])));
+ WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->cmd_hdr[i])));
+ WRITE_REG32(base, DLVRY_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS);
+
+ WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->complete_hdr[i])));
+ WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->complete_hdr[i])));
+ WRITE_REG32(base, COMPL_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS);
+ }
+
+ WRITE_REG32(base, ITCT_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->itct)));
+ WRITE_REG32(base, ITCT_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->itct)));
+
+ WRITE_REG32(base, IOST_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->iost)));
+ WRITE_REG32(base, IOST_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->iost)));
+
+ WRITE_REG32(base, BROKEN_MSG_ADDR_LO, lower_32_bits((UINT64)(hba->breakpoint)));
+ WRITE_REG32(base, BROKEN_MSG_ADDR_HI, upper_32_bits((UINT64)(hba->breakpoint)));
+
+ for (i = 0; i < PHY_CNT; i++) {
+ // Clear interrupt status
+ val = PHY_READ_REG32(base, CHL_INT0, i);
+ PHY_WRITE_REG32(base, CHL_INT0, i, val);
+ val = PHY_READ_REG32(base, CHL_INT1, i);
+ PHY_WRITE_REG32(base, CHL_INT1, i, val);
+ val = PHY_READ_REG32(base, CHL_INT2, i);
+ PHY_WRITE_REG32(base, CHL_INT2, i, val);
+
+ // Bypass chip bug mask abnormal intr
+ PHY_WRITE_REG32(base, CHL_INT0_MSK, i, 0x3fffff & ~CHL_INT0_MSK_PHYCTRL_NOTRDY);
+ }
+
+ // Init phy
+ for (i = 0; i < PHY_CNT; i++) {
+ PHY_WRITE_REG32(base, TX_ID_DWORD0, i, 0x10010e00);
+ PHY_WRITE_REG32(base, TX_ID_DWORD1, i, 0x16);
+ PHY_WRITE_REG32(base, TX_ID_DWORD2, i, 0x20880150);
+ PHY_WRITE_REG32(base, TX_ID_DWORD3, i, 0x16);
+ PHY_WRITE_REG32(base, TX_ID_DWORD4, i, 0x20880150);
+ PHY_WRITE_REG32(base, TX_ID_DWORD5, i, 0x0);
+
+ val = PHY_READ_REG32(base, PHY_CFG, i);
+ val &= ~PHY_CFG_DC_OPT_MSK;
+ val |= 1 << PHY_CFG_DC_OPT_OFF;
+ PHY_WRITE_REG32(base, PHY_CFG, i, val);
+
+ val = PHY_READ_REG32(base, PHY_CONFIG2, i);
+ val &= ~PHY_CONFIG2_FORCE_TXDEEMPH_MSK;
+ PHY_WRITE_REG32(base, PHY_CONFIG2, i, val);
+
+ val = PHY_READ_REG32(base, PHY_CFG, i);
+ val |= PHY_CFG_ENA_MSK;
+ PHY_WRITE_REG32(base, PHY_CFG, i, val);
+ }
+}
+
+STATIC VOID sas_init(SAS_V1_INFO *SasV1Info, PLATFORM_SAS_PROTOCOL *plat)
+{
+ struct hisi_hba *hba = SasV1Info->hba;
+ int i, s;
+
+ for (i = 0; i < QUEUE_CNT; i++) {
+ s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS;
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->cmd_hdr[i]);
+ ASSERT (hba->cmd_hdr[i] != NULL);
+ ZeroMem (hba->cmd_hdr[i], s);
+
+ s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS;
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->complete_hdr[i]);
+ ASSERT (hba->complete_hdr[i] != NULL);
+ ZeroMem (hba->complete_hdr[i], s);
+
+ s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS;
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->status_buf[i]);
+ ASSERT (hba->status_buf[i] != NULL);
+ ZeroMem (hba->status_buf[i], s);
+
+ s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS;
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->command_table[i]);
+ ASSERT (hba->command_table[i] != NULL);
+ ZeroMem (hba->command_table[i], s);
+
+ s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS;
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->sge[i]);
+ ASSERT (hba->sge[i] != NULL);
+ ZeroMem (hba->sge[i], s);
+ }
+
+ s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost);
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->iost);
+ ASSERT (hba->iost != NULL);
+ ZeroMem (hba->iost, s);
+
+ s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint);
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->breakpoint);
+ ASSERT (hba->breakpoint != NULL);
+ ZeroMem (hba->breakpoint, s);
+
+ s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+ DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->itct);
+ ASSERT (hba->itct != NULL);
+ ZeroMem (hba->itct, s);
+
+ hba->slots = AllocateZeroPool (SLOT_ENTRIES * sizeof(struct hisi_sas_slot));
+ ASSERT (hba->slots != NULL);
+
+ hisi_sas_v1_init(hba, plat);
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruFunction (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
+ struct hisi_hba *hba = SasV1Info->hba;
+
+ return prepare_cmd(hba, Packet);
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruGetNextTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **Target,
+ IN OUT UINT64 *Lun
+ )
+{
+ SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
+ struct hisi_hba *hba = SasV1Info->hba;
+ UINT8 ScsiId[TARGET_MAX_BYTES];
+ UINT8 TargetId;
+
+ if (*Target == NULL || Lun == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SetMem (ScsiId, TARGET_MAX_BYTES, 0xFF);
+
+ TargetId = (*Target)[0];
+
+ if (TargetId == MAX_TARGET_ID) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (CompareMem(*Target, ScsiId, TARGET_MAX_BYTES) == 0) {
+ SetMem (*Target, TARGET_MAX_BYTES,0);
+ } else {
+ (*Target)[0] = (UINT8) (hba->LatestTargetId + 1);
+ }
+
+ *Lun = 0;
+
+ //
+ // Update the LatestTargetId.
+ //
+ hba->LatestTargetId = (*Target)[0];
+ hba->LatestLun = *Lun;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruBuildDevicePath (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
+
+ *DevicePath = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)(SasV1Info->DevicePath));
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruGetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT8 **Target,
+ OUT UINT64 *Lun
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruResetChannel (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
+ )
+{
+
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruResetTarget (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun
+ )
+{
+
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+SasV1ExtScsiPassThruGetNextTarget (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **Target
+ )
+{
+
+ return EFI_UNSUPPORTED;
+}
+
+STATIC EFI_EXT_SCSI_PASS_THRU_PROTOCOL SasV1ExtScsiPassThruProtocolTemplate = {
+ NULL,
+ SasV1ExtScsiPassThruFunction,
+ SasV1ExtScsiPassThruGetNextTargetLun,
+ SasV1ExtScsiPassThruBuildDevicePath,
+ SasV1ExtScsiPassThruGetTargetLun,
+ SasV1ExtScsiPassThruResetChannel,
+ SasV1ExtScsiPassThruResetTarget,
+ SasV1ExtScsiPassThruGetNextTarget
+};
+
+EFI_STATUS
+EFIAPI
+SasDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ PLATFORM_SAS_PROTOCOL *plat;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gPlatformSasProtocolGuid,
+ (VOID **) &plat,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close the Sas Host used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gPlatformSasProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SasDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_SAS_PROTOCOL *plat;
+ SAS_V1_INFO *SasV1Info = NULL;
+ SAS_V1_TRANSPORT_DEVICE_PATH *DevicePath;
+ UINT32 val, base;
+ int i, phy_id = 0;
+ struct hisi_sas_itct *itct;
+ struct hisi_hba *hba;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gPlatformSasProtocolGuid,
+ (VOID **) &plat,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+ return Status;
+ }
+
+ SasV1Info = AllocateZeroPool (sizeof (SAS_V1_INFO));
+ ASSERT (SasV1Info);
+ SasV1Info->Signature = SAS_DEVICE_SIGNATURE;
+
+ SasV1Info->hba = AllocateZeroPool (sizeof(struct hisi_hba));
+ ASSERT (SasV1Info->hba);
+ hba = SasV1Info->hba;
+ base = hba->base = plat->BaseAddr;
+
+ sas_init(SasV1Info, plat);
+
+ // Wait for sas controller phyup happen
+ MicroSecondDelay(100000);
+
+ for (i = 0; i < PHY_CNT; i++) {
+ val = PHY_READ_REG32(base, CHL_INT2, i);
+
+ if (val & CHL_INT2_SL_PHY_ENA) {
+ phy_id = i;
+ }
+ }
+
+ itct = &hba->itct[0]; //device_id = 0
+
+ hba->port_id = (READ_REG32(base, PHY_PORT_NUM_MA) >> (4 * phy_id)) & 0xf;
+ // Setup itct
+ itct->qw0 = 0x355;
+ itct->sas_addr = PHY_READ_REG32(base, RX_IDAF_DWORD3, phy_id);
+ itct->sas_addr = itct->sas_addr << 32 | PHY_READ_REG32(base, RX_IDAF_DWORD4, phy_id);
+ itct->qw2 = 0;
+
+ // Clear phyup
+ PHY_WRITE_REG32(base, CHL_INT2, phy_id, CHL_INT2_SL_PHY_ENA);
+ val = PHY_READ_REG32(base, CHL_INT0, phy_id);
+ val &= ~CHL_INT0_PHYCTRL_NOTRDY;
+ PHY_WRITE_REG32(base, CHL_INT0, phy_id, val);
+ PHY_WRITE_REG32(base, CHL_INT0_MSK, phy_id, 0x3ce3ee);
+
+ // Need notify
+ val = PHY_READ_REG32(base, SL_CONTROL, phy_id);
+ val |= SL_CONTROL_NOTIFY_EN;
+ PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val);
+ // wait 100ms required for notify takes effect, refer drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+ MicroSecondDelay(100000);
+ val = PHY_READ_REG32(base, SL_CONTROL, phy_id);
+ val &= ~SL_CONTROL_NOTIFY_EN;
+ PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val);
+
+ CopyMem (&SasV1Info->ExtScsiPassThru, &SasV1ExtScsiPassThruProtocolTemplate, sizeof (EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
+ SasV1Info->ExtScsiPassThruMode.AdapterId = 2;
+ SasV1Info->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
+ SasV1Info->ExtScsiPassThruMode.IoAlign = 64; //cache line align
+ SasV1Info->ExtScsiPassThru.Mode = &SasV1Info->ExtScsiPassThruMode;
+
+ DevicePath = (SAS_V1_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ sizeof (SAS_V1_TRANSPORT_DEVICE_PATH));
+ ASSERT (DevicePath != NULL);
+ SasV1Info->DevicePath = DevicePath;
+
+ CopyMem (&DevicePath->Vendor.Guid, &gPlatformSasProtocolGuid, sizeof (EFI_GUID));
+ DevicePath->PhysBase = base;
+ SetDevicePathNodeLength (&DevicePath->Vendor,
+ sizeof (*DevicePath) - sizeof (DevicePath->End));
+ SetDevicePathEndNode (&DevicePath->End);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiDevicePathProtocolGuid, DevicePath,
+ &gEfiExtScsiPassThruProtocolGuid, &SasV1Info->ExtScsiPassThru,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SasDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ SAS_V1_INFO *SasV1Info;
+ EFI_STATUS Status;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsi;
+ int i, s;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **) &ExtScsi,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SasV1Info = SAS_FROM_PASS_THRU(ExtScsi);
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ SasV1Info->DevicePath,
+ &gEfiExtScsiPassThruProtocolGuid,
+ &SasV1Info->ExtScsiPassThru,
+ NULL);
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gPlatformSasProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseEvent (SasV1Info->TimerEvent);
+
+ for (i = 0; i < QUEUE_CNT; i++) {
+ s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS;
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->cmd_hdr[i]);
+ s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS;
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->complete_hdr[i]);
+ s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS;
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->status_buf[i]);
+ s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS;
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->command_table[i]);
+ s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS;
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->sge[i]);
+ }
+
+ s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost);
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->iost);
+ s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint);
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->breakpoint);
+ s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+ DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->itct);
+
+ FreePool (SasV1Info->hba->slots);
+ FreePool (SasV1Info->hba);
+ FreePool (SasV1Info);
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gSasDriverBinding = {
+ SasDriverBindingSupported,
+ SasDriverBindingStart,
+ SasDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+SasV1Initialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSasDriverBinding,
+ ImageHandle,
+ NULL,
+ NULL
+ );
+}
diff --git a/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf
new file mode 100644
index 0000000000..7e65cc819c
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/SasV1Dxe/SasV1Dxe.inf
@@ -0,0 +1,46 @@
+#/** @file
+#
+# Copyright (c) 2016 Linaro Ltd.
+# Copyright (c) 2016 Hisilicon Limited.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SasV1Dxe
+ FILE_GUID = 2b235921-8405-4219-a461-972a3a60969c
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SasV1Initialize
+
+
+[Sources.common]
+ SasV1Dxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ DmaLib
+ IoLib
+ MemoryAllocationLib
+ PcdLib
+ TimerLib
+ UefiDriverEntryPoint
+ UefiLib
+ UncachedMemoryAllocationLib
+
+[Protocols]
+ gEfiExtScsiPassThruProtocolGuid
+ gPlatformSasProtocolGuid
diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c
new file mode 100644
index 0000000000..8d8dacd3e0
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.c
@@ -0,0 +1,205 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "AddSmbiosType9.h"
+
+extern SMBIOS_TABLE_TYPE9 gPcieSlotInfo[];
+extern UINT8 OemGetPcieSlotNumber ();
+
+REPORT_PCIEDIDVID2BMC PcieDeviceToReport_2P[PCIEDEVICE_REPORT_MAX] = {
+ {67,0,0,0},
+ {225,0,0,3},
+ {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
+ {0xFFFF,0xFFFF,0xFFFF,0xFFFF}
+};
+VOID
+EFIAPI
+UpdateSmbiosType9Info(
+ IN OUT SMBIOS_TABLE_TYPE9 *Type9Record
+)
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN SegmentNumber;
+ UINTN BusNumber;
+ UINTN DeviceNumber;
+ UINTN FunctionNumber;
+ UINTN Index;
+ REPORT_PCIEDIDVID2BMC ReportPcieDidVid[PCIEDEVICE_REPORT_MAX];
+ if(OemIsMpBoot()){
+ (VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport_2P,sizeof(PcieDeviceToReport_2P));
+ } else {
+ (VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport,sizeof(PcieDeviceToReport));
+ }
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if(EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, " Locate gEfiPciIoProtocol Failed.\n"));
+ gBS->FreePool ((VOID *)HandleBuffer);
+ return;
+ }
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, __LINE__, Status));
+ continue;
+ }
+ (VOID)PciIo->GetLocation(PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber);
+ for(Index = 0; Index < sizeof(ReportPcieDidVid) / sizeof(REPORT_PCIEDIDVID2BMC); Index++){
+ if (Type9Record->SlotID == ReportPcieDidVid[Index].Slot + 1) {
+ if((BusNumber == ReportPcieDidVid[Index].Bus) && (DeviceNumber == ReportPcieDidVid[Index].Device)) {
+ DEBUG((EFI_D_ERROR,"PCIe device plot in slot Seg %d bdf %d %d %d\r\n",SegmentNumber,BusNumber,DeviceNumber,FunctionNumber));
+ Type9Record->SegmentGroupNum = SegmentNumber;
+ Type9Record->BusNum = BusNumber;
+ Type9Record->DevFuncNum = (DeviceNumber << 3) | FunctionNumber;
+ Type9Record->CurrentUsage = SlotUsageInUse;
+ break;
+ }
+ }
+ }
+ }
+ gBS->FreePool ((VOID *)HandleBuffer);
+ return;
+}
+EFI_STATUS
+EFIAPI
+AddSmbiosType9Entry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_TYPE SmbiosType;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+ SMBIOS_TABLE_TYPE9 *Type9Record;
+ SMBIOS_TABLE_TYPE9 *SmbiosRecord = NULL;
+ CHAR8 *OptionalStrStart;
+
+ UINT8 SmbiosAddType9Number;
+ UINT8 Index;
+
+ CHAR16 *SlotDesignation = NULL;
+ UINTN SlotDesignationStrLen;
+
+ Status = gBS->LocateProtocol (
+ &gEfiSmbiosProtocolGuid,
+ NULL,
+ (VOID **) &Smbios
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ do {
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ SmbiosType = EFI_SMBIOS_TYPE_SYSTEM_SLOTS;
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, &SmbiosType, &Record, NULL);
+ if (!EFI_ERROR(Status)) {
+ Status = Smbios->Remove (Smbios, SmbiosHandle);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Remove System Slot Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
+ break;
+ }
+ }
+ } while (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED);
+
+ SmbiosAddType9Number = OemGetPcieSlotNumber();
+
+ for (Index = 0; Index < SmbiosAddType9Number; Index++)
+ {
+ if (gPcieSlotInfo[Index].Hdr.Type != EFI_SMBIOS_TYPE_SYSTEM_SLOTS)
+ {
+ continue;
+ }
+
+ Type9Record = &gPcieSlotInfo[Index];
+
+ UpdateSmbiosType9Info (Type9Record);
+ SlotDesignation = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+ if (NULL == SlotDesignation)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
+
+ goto Exit;
+ }
+
+ SlotDesignationStrLen = UnicodeSPrint (SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE Slot%d", Type9Record->SlotID);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1);
+ if(NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
+
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, Type9Record, sizeof (SMBIOS_TABLE_TYPE9));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9);
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type09 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ goto Exit;
+ }
+
+ FreePool(SmbiosRecord);
+ FreePool(SlotDesignation);
+ }
+
+ return EFI_SUCCESS;
+
+Exit:
+ if(SmbiosRecord != NULL)
+ {
+ FreePool(SmbiosRecord);
+ }
+
+ if(SlotDesignation != NULL)
+ {
+ FreePool(SlotDesignation);
+ }
+
+ return Status;
+}
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h
new file mode 100644
index 0000000000..5766152399
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.h
@@ -0,0 +1,36 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#ifndef _ADD_SMBIOS_TYPE9_H_
+#define _ADD_SMBIOS_TYPE9_H_
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/OemMiscLib.h>
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf
new file mode 100644
index 0000000000..4db7b498bd
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/AddSmbiosType9/AddSmbiosType9.inf
@@ -0,0 +1,50 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AddSmbiosType9
+ FILE_GUID = 7AE6F104-66DF-48EF-B5A3-5050BF4908F0
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AddSmbiosType9Entry
+
+[Sources]
+ AddSmbiosType9.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugLib
+ UefiLib
+ UefiDriverEntryPoint
+ OemMiscLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid
+ gEfiPciIoProtocolGuid
+
+[Guids]
+
+[Pcd]
+
+[Depex]
+ gEfiSmbiosProtocolGuid AND
+ gEfiPciIoProtocolGuid
diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c
new file mode 100644
index 0000000000..da714c9e22
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.c
@@ -0,0 +1,762 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#include "MemorySubClass.h"
+
+EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
+EFI_HII_HANDLE mHiiHandle;
+
+UINT8 mMaxSkt;
+UINT8 mMaxCh;
+
+VOID
+SmbiosGetManufacturer (
+ IN UINT8 MfgIdLSB,
+ IN UINT8 MfgIdMSB,
+ OUT CHAR16 *Manufacturer
+)
+{
+ UINT32 Index = 0;
+
+ (VOID)StrCpyS(Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown");
+ while (JEP106[Index].MfgIdLSB != 0xFF && JEP106[Index].MfgIdMSB != 0xFF )
+ {
+ if (JEP106[Index].MfgIdLSB == MfgIdLSB && JEP106[Index].MfgIdMSB == MfgIdMSB)
+ {
+ (VOID)StrCpyS (Manufacturer, SMBIOS_STRING_MAX_LENGTH - 1, JEP106[Index].Name);
+ break;
+ }
+ Index++;
+ }
+}
+
+VOID
+SmbiosGetPartNumber (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm,
+ OUT CHAR16 *PartNumber
+ )
+{
+ CHAR16 StringBuffer2[SMBIOS_STRING_MAX_LENGTH];
+ UINT32 Index2;
+
+ (VOID)StrCpyS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, L"");
+ if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3)
+ {
+ for (Index2 = 0; Index2 < SPD_MODULE_PART; Index2++)
+ {
+ UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPart[Index2]);
+ (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2);
+ }
+ }
+ else
+ {
+ for (Index2 = 0; Index2 < SPD_MODULE_PART_DDR4; Index2++)
+ {
+ UnicodeSPrint (StringBuffer2, SMBIOS_STRING_MAX_LENGTH - 1, L"%c", pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdModPartDDR4[Index2]);
+ (VOID)StrCatS(PartNumber, SMBIOS_STRING_MAX_LENGTH - 1, StringBuffer2);
+ }
+ }
+
+ return;
+}
+
+VOID
+SmbiosGetSerialNumber (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm,
+ OUT CHAR16 *SerialNumber
+ )
+{
+ UINT32 Temp;
+
+ Temp = SwapBytes32 (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdSerialNum);
+
+ UnicodeSPrint(SerialNumber, SMBIOS_STRING_MAX_LENGTH, L"0x%08x", Temp);
+
+ return;
+}
+
+BOOLEAN
+IsDimmPresent (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm
+)
+{
+ if (pGblData->Channel[Skt][Ch].Status == FALSE ||
+ pGblData->Channel[Skt][Ch].Dimm[Dimm].Status == FALSE)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+UINT8
+SmbiosGetMemoryType (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm
+)
+{
+ UINT8 MemoryType;
+
+ if(!IsDimmPresent(pGblData, Skt, Ch, Dimm))
+ {
+ return MemoryTypeUnknown;
+ }
+
+ if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3)
+ {
+ MemoryType = MemoryTypeDdr3;
+ }
+ else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4)
+ {
+ MemoryType = MemoryTypeDdr4;
+ }
+ else
+ {
+ MemoryType = MemoryTypeUnknown;
+ }
+
+ return MemoryType;
+}
+
+VOID
+SmbiosGetTypeDetail (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm,
+ IN OUT MEMORY_DEVICE_TYPE_DETAIL *TypeDetail
+)
+{
+ if (NULL == TypeDetail)
+ {
+ return;
+ }
+
+ if(!IsDimmPresent(pGblData, Skt, Ch, Dimm))
+ {
+ TypeDetail->Unknown = 1;
+ return;
+ }
+
+ switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].ModuleType)
+ {
+ case SPD_UDIMM:
+ TypeDetail->Unbuffered = 1;
+ break;
+
+ case SPD_LRDIMM:
+ TypeDetail->LrDimm = 1;
+ break;
+
+ case SPD_RDIMM:
+ TypeDetail->Registered = 1;
+ break;
+
+ default:
+ TypeDetail->Unknown = 1;
+ break;
+ }
+}
+
+VOID
+SmbiosGetDimmVoltageInfo (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm,
+ IN OUT SMBIOS_TABLE_TYPE17 *Type17Record
+
+)
+{
+ if(!IsDimmPresent(pGblData, Skt, Ch, Dimm))
+ {
+ return;
+ }
+
+ if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR3)
+ {
+ Type17Record->MinimumVoltage = 1250;
+ Type17Record->MaximumVoltage = 1500;
+
+ switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd)
+ {
+ case SPD_VDD_150:
+ Type17Record->ConfiguredVoltage = 1500;
+ break;
+
+ case SPD_VDD_135:
+ Type17Record->ConfiguredVoltage = 1350;
+ break;
+
+ case SPD_VDD_125:
+ Type17Record->ConfiguredVoltage = 1250;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (pGblData->Channel[Skt][Ch].Dimm[Dimm].DramType == SPD_TYPE_DDR4)
+ {
+ Type17Record->MinimumVoltage = 1200;
+ Type17Record->MaximumVoltage = 2000;
+ switch (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdVdd)
+ {
+ case SPD_VDD_120:
+ Type17Record->ConfiguredVoltage = 1200;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+VOID
+SmbiosGetMemoryDevicesNumber (
+ IN OUT UINT16 *NumberOfDevices
+)
+{
+ UINT8 Skt, Ch, Dimm;
+
+ for(Skt = 0; Skt < mMaxSkt; Skt++)
+ {
+ for(Ch = 0; Ch < mMaxCh; Ch++)
+ {
+ for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++)
+ {
+ (*NumberOfDevices)++;
+ }
+ }
+ }
+}
+
+UINT8
+SmbiosGetPartitionWidth (
+)
+{
+
+ UINT8 Skt, Ch, Dimm;
+ UINT8 PartitionWidth = 0;
+
+ for(Skt = 0; Skt < mMaxSkt; Skt++)
+ {
+ for(Ch = 0; Ch < mMaxCh; Ch++)
+ {
+ for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++)
+ {
+ PartitionWidth++;
+ }
+ }
+ }
+
+ return PartitionWidth;
+}
+
+EFI_STATUS
+SmbiosAddType16Table (
+ IN pGBL_DATA pGblData,
+ OUT EFI_SMBIOS_HANDLE *MemArraySmbiosHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT64 MemoryCapacity;
+ SMBIOS_TABLE_TYPE16 *Type16Record;
+
+ UINT16 NumberOfMemoryDevices = 0;
+
+ SmbiosGetMemoryDevicesNumber (&NumberOfMemoryDevices);
+
+ MemoryCapacity = (UINT64) LShiftU64 (NumberOfMemoryDevices * MAX_DIMM_SIZE, 20); // GB to KB.
+
+ //
+ // Type 16 SMBIOS Record
+ //
+ Type16Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);
+ if (NULL == Type16Record)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY;
+ Type16Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE16);
+ Type16Record->Hdr.Handle = 0x0;
+ Type16Record->Location = MemoryArrayLocationSystemBoard;
+ Type16Record->Use = MemoryArrayUseSystemMemory;
+ Type16Record->MemoryErrorInformationHandle = 0xFFFE;
+ Type16Record->NumberOfMemoryDevices = NumberOfMemoryDevices;
+
+ if(pGblData->EccEn)
+ {
+ Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionSingleBitEcc;
+ }
+ else
+ {
+ Type16Record->MemoryErrorCorrection = MemoryErrorCorrectionNone;
+ }
+
+ if (MemoryCapacity >= 0x80000000)
+ {
+ Type16Record->MaximumCapacity = 0x80000000; // in KB;
+ Type16Record->ExtendedMaximumCapacity = MemoryCapacity << 10; // Extended Max capacity should be stored in bytes.
+ }
+ else
+ {
+ Type16Record->MaximumCapacity = (UINT32)MemoryCapacity; // Max capacity should be stored in kilo bytes.
+ Type16Record->ExtendedMaximumCapacity = 0;
+ }
+
+ *MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type16Record);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type16 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(Type16Record);
+ return Status;
+}
+
+EFI_STATUS
+SmbiosAddType19Table (
+ IN pGBL_DATA pGblData,
+ IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MemInfoTotalMem;
+ UINT64 TotalMemorySize;
+ EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
+ SMBIOS_TABLE_TYPE19 *Type19Record;
+
+ MemInfoTotalMem = pGblData->MemSize; // In MB
+
+ if (MemInfoTotalMem == 0)
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ TotalMemorySize = (UINT64) LShiftU64 (MemInfoTotalMem, 10); // MB to KB.
+
+ //
+ // Type 19 SMBIOS Record
+ //
+ Type19Record = AllocateZeroPool(sizeof(SMBIOS_TABLE_TYPE19) + 1 + 1);
+ if (NULL == Type19Record)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
+ Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
+ Type19Record->Hdr.Handle = 0x0;
+ Type19Record->StartingAddress = 0x0;
+ Type19Record->EndingAddress = (UINT32) (TotalMemorySize - 1); // in KB;
+ Type19Record->MemoryArrayHandle = MemArraySmbiosHandle;
+ Type19Record->PartitionWidth = SmbiosGetPartitionWidth ();
+ Type19Record->ExtendedStartingAddress = 0x0;
+ Type19Record->ExtendedEndingAddress = 0x0;
+
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type19Record);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type19 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(Type19Record);
+ return Status;
+}
+
+
+EFI_STATUS
+SmbiosAddType17Table (
+ IN pGBL_DATA pGblData,
+ IN UINT8 Skt,
+ IN UINT8 Ch,
+ IN UINT8 Dimm,
+ IN EFI_SMBIOS_HANDLE MemArraySmbiosHandle
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_TABLE_TYPE17 *Type17Record;
+ EFI_SMBIOS_HANDLE MemDevSmbiosHandle;
+ UINTN TableSize;
+
+ UINTN StringBufferSize;
+ EFI_STRING StringBuffer;
+ UINT16 MemInfoMemFreq;
+ UINT16 MemoryTotalWidth;
+ UINT16 MemoryDataWidth;
+ UINT16 MemoryDeviceSize;
+ UINT16 MemorySpeed;
+ UINT8 Attributes;
+ UINT32 MemoryDeviceExtendSize;
+ UINT16 CfgMemorySpeed;
+
+ CHAR8 *OptionalStrStart;
+ UINTN DeviceLocatorStrLen;
+ UINTN BankLocatorStrLen;
+ UINTN ManufactureStrLen;
+ UINTN SerialNumberStrLen;
+ UINTN AssertTagStrLen;
+ UINTN PartNumberStrLen;
+ EFI_STRING DeviceLocatorStr;
+ EFI_STRING BankLocatorStr;
+ EFI_STRING ManufactureStr;
+ EFI_STRING SerialNumberStr;
+ EFI_STRING AssertTagStr;
+ EFI_STRING PartNumberStr;
+ EFI_STRING_ID DeviceLocator;
+
+ Type17Record = NULL;
+ DeviceLocatorStr = NULL;
+ BankLocatorStr = NULL;
+ ManufactureStr = NULL;
+ SerialNumberStr = NULL;
+ AssertTagStr = NULL;
+ PartNumberStr = NULL;
+
+ MemoryTotalWidth = 0;
+ MemoryDataWidth = 0;
+ MemoryDeviceSize = 0;
+ MemoryDeviceExtendSize = 0;
+ MemorySpeed = 0;
+ Attributes = 0;
+ CfgMemorySpeed = 0;
+
+ //
+ // Allocate Buffers
+ //
+ StringBufferSize = (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH;
+ StringBuffer = AllocateZeroPool (StringBufferSize);
+ if(NULL == StringBuffer)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+
+ //
+ // Manufacture
+ //
+ ManufactureStr = AllocateZeroPool (StringBufferSize);
+ if(NULL == ManufactureStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_BUF;
+ }
+ UnicodeSPrint(ManufactureStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM");
+
+ //
+ // SerialNumber
+ //
+ SerialNumberStr = AllocateZeroPool (StringBufferSize);
+ if(NULL == SerialNumberStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_MAN;
+ }
+ UnicodeSPrint(SerialNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM");
+
+ //
+ // AssetTag
+ //
+ AssertTagStr = AllocateZeroPool (StringBufferSize);
+ if(NULL == AssertTagStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_SN;
+ }
+ UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM");
+
+ //
+ // PartNumber
+ //
+ PartNumberStr = AllocateZeroPool (StringBufferSize);
+ if(NULL == PartNumberStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_AST;
+ }
+ UnicodeSPrint(PartNumberStr, SMBIOS_STRING_MAX_LENGTH - 1, L"NO DIMM");
+
+
+ if(IsDimmPresent(pGblData, Skt, Ch, Dimm))
+ {
+ MemoryDataWidth = pGblData->Channel[Skt][Ch].Dimm[Dimm].PrimaryBusWidth;
+ MemoryTotalWidth = MemoryDataWidth + pGblData->Channel[Skt][Ch].Dimm[Dimm].ExtensionBusWidth;
+
+ MemoryDeviceSize = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSize; //in MB
+ MemoryDeviceExtendSize = 0;
+
+ if (MemoryDeviceSize >= 0x7fff)
+ {
+ MemoryDeviceExtendSize = MemoryDeviceSize; // in MB
+ MemoryDeviceSize = 0x7fff; // max value
+ }
+
+ MemInfoMemFreq = pGblData->Freq;
+ MemorySpeed = pGblData->Channel[Skt][Ch].Dimm[Dimm].DimmSpeed;
+ Attributes = pGblData->Channel[Skt][Ch].Dimm[Dimm].RankNum;
+ CfgMemorySpeed = MemInfoMemFreq;
+
+ //
+ // Manufacturer
+ //
+ SmbiosGetManufacturer (pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId & 0xFF,
+ pGblData->Channel[Skt][Ch].Dimm[Dimm].SpdMMfgId >> 8,
+ ManufactureStr
+ );
+
+ //
+ // SerialNumber
+ //
+ SmbiosGetSerialNumber(pGblData, Skt, Ch, Dimm, SerialNumberStr);
+
+ //
+ // AssetTag
+ //
+ UnicodeSPrint(AssertTagStr, SMBIOS_STRING_MAX_LENGTH - 1, L"Unknown");
+
+ //
+ // PartNumber
+ //
+ SmbiosGetPartNumber(pGblData, Skt, Ch, Dimm, PartNumberStr);
+ }
+
+ //
+ // DeviceLocator
+ //
+ DeviceLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+ if(NULL == DeviceLocatorStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_PN;
+ }
+ DeviceLocator = gDimmToDevLocator[Skt][Ch][Dimm];
+ if (DeviceLocator != 0xFFFF)
+ {
+ UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x ", Skt, Ch, Dimm);
+ StringBuffer = HiiGetPackageString (&gEfiCallerIdGuid, DeviceLocator, NULL);
+ (VOID)StrCatS(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, StringBuffer);
+ }
+ else
+ {
+ UnicodeSPrint(DeviceLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"DIMM%x%x%x", Skt, Ch, Dimm);
+ }
+ DeviceLocatorStrLen = StrLen (DeviceLocatorStr);
+
+ //
+ // BankLocator
+ //
+ BankLocatorStr = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+ if(NULL == BankLocatorStr)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_STR_DEV;
+ }
+ UnicodeSPrint(BankLocatorStr, SMBIOS_STRING_MAX_LENGTH, L"SOCKET %x CHANNEL %x DIMM %x", Skt, Ch, Dimm);
+ BankLocatorStrLen = StrLen (BankLocatorStr);
+
+ ManufactureStrLen = StrLen (ManufactureStr);
+ SerialNumberStrLen = StrLen (SerialNumberStr);
+ AssertTagStrLen = StrLen (AssertTagStr);
+ PartNumberStrLen = StrLen (PartNumberStr);
+
+ //
+ // Report Type 17 SMBIOS Record
+ //
+ TableSize = sizeof(SMBIOS_TABLE_TYPE17) + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1 + PartNumberStrLen + 1 + 1;
+ Type17Record = AllocateZeroPool (TableSize);
+ if(NULL == Type17Record)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_BL;
+ }
+
+ Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
+ Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);
+ Type17Record->Hdr.Handle = 0;
+ Type17Record->MemoryArrayHandle = MemArraySmbiosHandle;
+ Type17Record->MemoryErrorInformationHandle = 0xFFFE;
+ Type17Record->TotalWidth = MemoryTotalWidth;
+ Type17Record->DataWidth = MemoryDataWidth;
+ Type17Record->Size = MemoryDeviceSize; // in MB
+ Type17Record->FormFactor = MemoryFormFactorDimm;
+ Type17Record->DeviceLocator = 1;
+ Type17Record->BankLocator = 2;
+ Type17Record->MemoryType = SmbiosGetMemoryType (pGblData, Skt, Ch, Dimm);
+
+ Type17Record->TypeDetail.Synchronous = 1;
+
+ SmbiosGetTypeDetail (pGblData, Skt, Ch, Dimm, &(Type17Record->TypeDetail));
+
+ Type17Record->Speed = MemorySpeed; // in MHZ
+ Type17Record->Manufacturer = 3;
+ Type17Record->SerialNumber = 4;
+ Type17Record->AssetTag = 5;
+ Type17Record->PartNumber = 6;
+ Type17Record->Attributes = Attributes;
+ Type17Record->ExtendedSize = MemoryDeviceExtendSize;
+ Type17Record->ConfiguredMemoryClockSpeed = CfgMemorySpeed;
+ //
+ // Add for smbios 2.8.0
+ //
+ SmbiosGetDimmVoltageInfo (pGblData, Skt, Ch, Dimm, Type17Record);
+
+ OptionalStrStart = (CHAR8 *) (Type17Record + 1);
+ UnicodeStrToAsciiStr (DeviceLocatorStr, OptionalStrStart);
+ UnicodeStrToAsciiStr (BankLocatorStr, OptionalStrStart + DeviceLocatorStrLen + 1);
+ UnicodeStrToAsciiStr (ManufactureStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1);
+ UnicodeStrToAsciiStr (SerialNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1);
+ UnicodeStrToAsciiStr (AssertTagStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1);
+ UnicodeStrToAsciiStr (PartNumberStr, OptionalStrStart + DeviceLocatorStrLen + 1 + BankLocatorStrLen + 1 + ManufactureStrLen + 1 + SerialNumberStrLen + 1 + AssertTagStrLen + 1);
+
+ MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type17 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool (Type17Record);
+
+FREE_BL:
+ FreePool (BankLocatorStr);
+
+FREE_STR_DEV:
+ FreePool (DeviceLocatorStr);
+
+FREE_STR_PN:
+ FreePool (PartNumberStr);
+
+FREE_STR_AST:
+ FreePool (AssertTagStr);
+
+FREE_STR_SN:
+ FreePool (SerialNumberStr);
+
+FREE_STR_MAN:
+ FreePool (ManufactureStr);
+
+FREE_STR_BUF:
+ FreePool (StringBuffer);
+
+ return Status;
+}
+
+
+/**
+ Standard EFI driver point. This driver locates the MemoryConfigurationData Variable,
+ if it exists, add the related SMBIOS tables by PI SMBIOS protocol.
+
+ @param ImageHandle Handle for the image of this driver
+ @param SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The data was successfully stored.
+
+**/
+EFI_STATUS
+EFIAPI
+MemorySubClassEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ pGBL_DATA pGblData;
+ EFI_SMBIOS_HANDLE MemArraySmbiosHandle;
+ UINT8 Skt, Ch, Dimm;
+
+ GuidHob = GetFirstGuidHob(&gHisiEfiMemoryMapGuid);
+ if(NULL == GuidHob)
+ {
+ DEBUG((EFI_D_ERROR, "Could not get MemoryMap Guid hob. %r\n"));
+ return EFI_NOT_FOUND;
+ }
+ pGblData = (pGBL_DATA) GET_GUID_HOB_DATA(GuidHob);
+
+ //
+ // Locate dependent protocols
+ //
+ Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));
+ return Status;
+ }
+ mSmbios = Smbios;
+
+ //
+ // Add our default strings to the HII database. They will be modified later.
+ //
+ mHiiHandle = OemGetPackages();
+ if(NULL == mHiiHandle)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mMaxSkt = OemGetSocketNumber();
+ mMaxCh = OemGetDdrChannel();
+ // Get DIMM slot number on Socket 0 Channel 0
+ // TODO: Assume all channels have same slot number
+
+ Status = SmbiosAddType16Table (pGblData, &MemArraySmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Smbios Add Type16 Table Failed. %r\n", Status));
+ return Status;
+ }
+
+ Status = SmbiosAddType19Table (pGblData, MemArraySmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Smbios Add Type19 Table Failed. %r\n", Status));
+ return Status;
+ }
+
+ for(Skt = 0; Skt < mMaxSkt; Skt++)
+ {
+ for(Ch = 0; Ch < mMaxCh; Ch++)
+ {
+ for(Dimm = 0; Dimm < OemGetDimmSlot(Skt, Ch); Dimm++)
+ {
+ Status = SmbiosAddType17Table (pGblData, Skt, Ch, Dimm, MemArraySmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Smbios Add Type17 Table Failed. %r\n", Status));
+ }
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h
new file mode 100644
index 0000000000..c35ce39d61
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClass.h
@@ -0,0 +1,79 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#ifndef _MEMORY_SUBCLASS_DRIVER_H
+#define _MEMORY_SUBCLASS_DRIVER_H
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/HiiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+
+#include <Library/HwMemInitLib.h>
+#include <Guid/DebugMask.h>
+#include <Guid/MemoryMapData.h>
+#include <Library/PlatformSysCtrlLib.h>
+#include <Library/OemMiscLib.h>
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+extern UINT8 MemorySubClassStrings[];
+
+#define MAX_DIMM_SIZE 32 // In GB
+
+struct SPD_JEDEC_MANUFACTURER
+{
+ UINT8 MfgIdLSB;
+ UINT8 MfgIdMSB;
+ CHAR16 *Name;
+};
+
+struct SPD_JEDEC_MANUFACTURER JEP106[] = {
+ { 0, 0x10, L"NEC"},
+ { 0, 0x2c, L"Micron"},
+ { 0, 0x3d, L"Tektronix"},
+ { 0, 0x97, L"TI"},
+ { 0, 0xad, L"Hynix"},
+ { 0, 0xb3, L"IDT"},
+ { 0, 0xc1, L"Infineon"},
+ { 0, 0xce, L"Samsung"},
+ { 1, 0x94, L"Smart"},
+ { 1, 0x98, L"Kingston"},
+ { 2, 0xc8, L"Agilent"},
+ { 2, 0xfe, L"Elpida"},
+ { 3, 0x0b, L"Nanya"},
+ { 4, 0x43, L"Ramaxel"},
+ { 4, 0xb3, L"Inphi"},
+ { 5, 0x51, L"Qimonda"},
+ { 5, 0x57, L"AENEON"},
+ { 0xFF, 0xFF, L""}
+};
+
+
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf
new file mode 100644
index 0000000000..93a2bcac37
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassDxe.inf
@@ -0,0 +1,59 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MemorySubClass
+ FILE_GUID = 62194F1A-5A0D-4B33-9EF0-7D05C6CB923A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MemorySubClassEntryPoint
+
+[Sources]
+ MemorySubClassStrings.uni
+ MemorySubClass.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ HobLib
+ HiiLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ PrintLib
+ PlatformSysCtrlLib
+ PcdLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+
+[Guids]
+ gHisiEfiMemoryMapGuid
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni
new file mode 100644
index 0000000000..edf8464e5c
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/MemorySubClassDxe/MemorySubClassStrings.uni
@@ -0,0 +1,30 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. All rights reserved.
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+//
+// Begin English Language Strings
+//
+
+#string STR_MEMORY_SUBCLASS_UNKNOWN #language en-US "Unknown"
+
+//
+// End English Language Strings
+//
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
new file mode 100644
index 0000000000..61473e85b8
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
@@ -0,0 +1,728 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "ProcessorSubClass.h"
+
+#include <FrameworkDxe.h>
+
+EFI_HII_HANDLE mHiiHandle;
+
+EFI_SMBIOS_PROTOCOL *mSmbios;
+
+SMBIOS_TABLE_TYPE7 mSmbiosCacheTable[] = {
+ //L1 Instruction Cache
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE7), //Length
+ 0 //Handle
+ },
+ 1, //SocketDesignation
+ 0, //CacheConfiguration
+ 0, //MaximumCacheSize
+ 48, //InstalledSize
+ { //SupportedSRAMType
+ 0
+ },
+ { //CurrentSRAMType
+ 0
+ },
+ 0, //CacheSpeed
+ CacheErrorParity, //ErrorCorrectionType
+ CacheTypeInstruction, //SystemCacheType
+ CacheAssociativity8Way //Associativity
+ },
+
+ //L1 Data Cache
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE7), //Length
+ 0 //Handle
+ },
+ 1, //SocketDesignation
+ 0, //CacheConfiguration
+ 0, //MaximumCacheSize
+ 32, //InstalledSize
+ { //SupportedSRAMType
+ 0
+ },
+ { //CurrentSRAMType
+ 0
+ },
+ 0, //CacheSpeed
+ CacheErrorSingleBit, //ErrorCorrectionType
+ CacheTypeData, //SystemCacheType
+ CacheAssociativity8Way //Associativity
+ },
+
+ //L2 Cache
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE7), //Length
+ 0 //Handle
+ },
+ 1, //SocketDesignation
+ 0, //CacheConfiguration
+ 0, //MaximumCacheSize
+ 4096, //InstalledSize
+ { //SupportedSRAMType
+ 0
+ },
+ { //CurrentSRAMType
+ 0
+ },
+ 0, //CacheSpeed
+ CacheErrorSingleBit, //ErrorCorrectionType
+ CacheTypeUnified, //SystemCacheType
+ CacheAssociativity8Way //Associativity
+ },
+
+ //L3 Cache
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_CACHE_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE7), //Length
+ 0 //Handle
+ },
+ 1, //SocketDesignation
+ 0, //CacheConfiguration
+ 0, //MaximumCacheSize
+ 16384, //InstalledSize
+ { //SupportedSRAMType
+ 0
+ },
+ { //CurrentSRAMType
+ 0
+ },
+ 0, //CacheSpeed
+ CacheErrorSingleBit, //ErrorCorrectionType
+ CacheTypeUnified, //SystemCacheType
+ CacheAssociativity16Way //Associativity
+ }
+};
+
+SMBIOS_TABLE_TYPE4 mSmbiosProcessorTable[] = {
+ //CPU0
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE4), //Length
+ 0 //Handle
+ },
+ 1, //Socket
+ CentralProcessor, //ProcessorType
+ ProcessorFamilyOther, //ProcessorFamily
+ 2, //ProcessorManufacture
+ { //ProcessorId
+ { //Signature
+ 0
+ },
+ { //FeatureFlags
+ 0
+ }
+ },
+ 3, //ProcessorVersion
+ { //Voltage
+ 0
+ },
+ EXTERNAL_CLOCK, //ExternalClock
+ CPU_MAX_SPEED, //MaxSpeed
+ 0, //CurrentSpeed
+ 0, //Status
+ ProcessorUpgradeUnknown, //ProcessorUpgrade
+ 0xFFFF, //L1CacheHandle
+ 0xFFFF, //L2CacheHandle
+ 0xFFFF, //L3CacheHandle
+ 4, //SerialNumber
+ 5, //AssetTag
+ 6, //PartNumber
+
+ 0, //CoreCount
+ 0, //EnabledCoreCount
+ 0, //ThreadCount
+ 0, //ProcessorCharacteristics
+
+ ProcessorFamilyARM, //ProcessorFamily2
+
+ 0, //CoreCount2
+ 0, //EnabledCoreCount2
+ 0 //ThreadCount2
+ },
+
+ //CPU1
+ {
+ { //Header
+ EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, //Type
+ sizeof(SMBIOS_TABLE_TYPE4), //Length
+ 0 //Handle
+ },
+ 1, //Socket
+ CentralProcessor, //ProcessorType
+ ProcessorFamilyOther, //ProcessorFamily
+ 2, //ProcessorManufacture
+ { //ProcessorId
+ { //Signature
+ 0
+ },
+ { //FeatureFlags
+ 0
+ }
+ },
+ 3, //ProcessorVersion
+ { //Voltage
+ 0
+ },
+ EXTERNAL_CLOCK, //ExternalClock
+ CPU_MAX_SPEED, //MaxSpeed
+ 0, //CurrentSpeed
+ 0, //Status
+ ProcessorUpgradeUnknown, //ProcessorUpgrade
+ 0xFFFF, //L1CacheHandle
+ 0xFFFF, //L2CacheHandle
+ 0xFFFF, //L3CacheHandle
+ 4, //SerialNumber
+ 5, //AssetTag
+ 6, //PartNumber
+
+ 0, //CoreCount
+ 0, //EnabledCoreCount
+ 0, //ThreadCount
+ 0, //ProcessorCharacteristics
+
+ ProcessorFamilyARM, //ProcessorFamily2
+
+ 0, //CoreCount2
+ 0, //EnabledCoreCount2
+ 0 //ThreadCount2
+ }
+};
+
+
+UINT16
+GetCpuFrequency (
+ IN UINT8 ProcessorNumber
+)
+{
+ return (UINT16)(PlatformGetCpuFreq(ProcessorNumber)/1000/1000);
+}
+
+UINTN
+GetCacheSocketStr (
+ IN UINT8 CacheLevel,
+ OUT CHAR16 *CacheSocketStr
+ )
+{
+ UINTN CacheSocketStrLen;
+
+ if(CacheLevel == CPU_CACHE_L1_Instruction)
+ {
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Instruction Cache", CacheLevel + 1);
+ }
+ else if(CacheLevel == CPU_CACHE_L1_Data)
+ {
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Data Cache", CacheLevel);
+ }
+ else
+ {
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, SMBIOS_STRING_MAX_LENGTH - 1, L"L%x Cache", CacheLevel);
+ }
+
+ return CacheSocketStrLen;
+}
+
+VOID
+UpdateSmbiosCacheTable (
+ IN UINT8 CacheLevel
+ )
+{
+ UINT16 CoreCount;
+ UINT32 TotalSize;
+ UINT32 CacheSize;
+ UINT16 MaximumCacheSize;
+ UINT16 InstalledSize;
+ CACHE_CONFIGURATION CacheConfig;
+ CACHE_SRAM_TYPE_DATA CacheSramType = {0};
+
+ CoreCount = 16; // Default value is 16 Core
+
+ //
+ // Set Cache Configuration
+ //
+ CacheConfig.Bits.Socketed = 0; // Not Socketed
+ CacheConfig.Bits.Reserved1 = 0; //
+ CacheConfig.Bits.Location = 0; // Internal
+ CacheConfig.Bits.Enable = 1; // Enabled
+ CacheConfig.Bits.Reserved2 = 0;
+ if(CacheLevel == CPU_CACHE_L1_Instruction || CacheLevel == CPU_CACHE_L1_Data)
+ {
+ CacheConfig.Bits.Level = 0;
+ CacheConfig.Bits.OperationalMode = 1; // Write Back
+ }
+ else
+ {
+ CacheConfig.Bits.Level = CacheLevel - 1;
+ CacheConfig.Bits.OperationalMode = 2; // Varies with Memory Address
+ }
+
+ mSmbiosCacheTable[CacheLevel].CacheConfiguration = CacheConfig.Data;
+
+ //
+ // Set Cache Size
+ //
+ CacheSize = mSmbiosCacheTable[CacheLevel].InstalledSize;
+ if (PACKAGE_16CORE != PlatformGetPackageType()) // 32 Core
+ {
+ CoreCount = CoreCount * 2;
+
+ if (CacheLevel > 1)
+ {
+ CacheSize = CacheSize * 2;
+ }
+ }
+
+ if(CacheLevel <= 1)
+ {
+ TotalSize = CacheSize * CoreCount;
+ }
+ else
+ {
+ TotalSize = CacheSize;
+ }
+
+ if((TotalSize >> 15) == 0) // 1K granularity
+ {
+ MaximumCacheSize = (UINT16)TotalSize;
+ InstalledSize = (UINT16)TotalSize;
+ }
+ else // 64K granularity
+ {
+ MaximumCacheSize = (UINT16)(TotalSize >> 6);
+ InstalledSize = (UINT16)(TotalSize >> 6);
+
+ // Set BIT15 to 1
+ MaximumCacheSize |= BIT15;
+ InstalledSize |= BIT15;
+ }
+
+ mSmbiosCacheTable[CacheLevel].MaximumCacheSize = MaximumCacheSize;
+ mSmbiosCacheTable[CacheLevel].InstalledSize = InstalledSize;
+
+ //
+ // Set SRAM Type
+ //
+ CacheSramType.Synchronous = 1;
+ (VOID)CopyMem(&mSmbiosCacheTable[CacheLevel].SupportedSRAMType, &CacheSramType, sizeof(CACHE_SRAM_TYPE_DATA));
+ (VOID)CopyMem(&mSmbiosCacheTable[CacheLevel].CurrentSRAMType, &CacheSramType, sizeof(CACHE_SRAM_TYPE_DATA));
+}
+
+/**
+ Add Type 7 SMBIOS Record for Cache Information.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+ @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
+ @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
+ @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
+
+**/
+EFI_STATUS
+AddSmbiosCacheTypeTable (
+ IN UINTN ProcessorNumber,
+ OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
+ OUT EFI_SMBIOS_HANDLE *L3CacheHandle
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_TABLE_TYPE7 *Type7Record;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ UINTN TableSize;
+ UINT8 CacheLevel;
+ CHAR8 *OptionalStrStart;
+ EFI_STRING CacheSocketStr;
+ UINTN CacheSocketStrLen;
+ UINTN StringBufferSize;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get Cache information
+ //
+ for(CacheLevel = 0; CacheLevel < MAX_CACHE_LEVEL; CacheLevel++)
+ {
+ Type7Record = NULL;
+
+ if(mSmbiosCacheTable[CacheLevel].InstalledSize == 0)
+ {
+ continue;
+ }
+
+ //
+ // Update Cache information
+ //
+ if (mSmbiosCacheTable[CacheLevel].MaximumCacheSize == 0)
+ {
+ UpdateSmbiosCacheTable (CacheLevel);
+ }
+
+ StringBufferSize = sizeof(CHAR16) * SMBIOS_STRING_MAX_LENGTH;
+ CacheSocketStr = AllocateZeroPool(StringBufferSize);
+ if (CacheSocketStr == NULL)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CacheSocketStrLen = GetCacheSocketStr (CacheLevel, CacheSocketStr);
+
+ TableSize = sizeof(SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;
+ Type7Record = AllocateZeroPool (TableSize);
+ if (Type7Record == NULL)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(Type7Record, &mSmbiosCacheTable[CacheLevel], sizeof (SMBIOS_TABLE_TYPE7));
+
+ OptionalStrStart = (CHAR8 *) (Type7Record + 1);
+ UnicodeStrToAsciiStr (CacheSocketStr, OptionalStrStart);
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type7Record);
+ if (EFI_ERROR (Status))
+ {
+ goto Exit;
+ }
+
+ // Config L1/L2/L3 Cache Handle
+ switch(CacheLevel)
+ {
+ case CPU_CACHE_L1_Instruction:
+ case CPU_CACHE_L1_Data:
+ *L1CacheHandle = SmbiosHandle;
+ break;
+ case CPU_CACHE_L2:
+ *L2CacheHandle = SmbiosHandle;
+ break;
+ case CPU_CACHE_L3:
+ *L3CacheHandle = SmbiosHandle;
+ break;
+ default :
+ break;
+ }
+Exit:
+ if(Type7Record != NULL)
+ {
+ FreePool (Type7Record);
+ }
+ if(CacheSocketStr != NULL)
+ {
+ FreePool (CacheSocketStr);
+ CacheSocketStr = NULL;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Add Type 4 SMBIOS Record for Processor Information.
+
+ @param[in] ProcessorNumber Processor number of specified processor.
+
+**/
+EFI_STATUS
+AddSmbiosProcessorTypeTable (
+ IN UINTN ProcessorNumber
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_TABLE_TYPE4 *Type4Record;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_HANDLE L1CacheHandle;
+ EFI_SMBIOS_HANDLE L2CacheHandle;
+ EFI_SMBIOS_HANDLE L3CacheHandle;
+
+ CHAR8 *OptionalStrStart;
+ EFI_STRING_ID ProcessorManu;
+ EFI_STRING_ID ProcessorVersion;
+ EFI_STRING_ID SerialNumber;
+ EFI_STRING_ID AssetTag;
+ EFI_STRING_ID PartNumber;
+ EFI_STRING ProcessorSocketStr;
+ EFI_STRING ProcessorManuStr;
+ EFI_STRING ProcessorVersionStr;
+ EFI_STRING SerialNumberStr;
+ EFI_STRING AssetTagStr;
+ EFI_STRING PartNumberStr;
+ UINTN ProcessorSocketStrLen;
+ UINTN ProcessorManuStrLen;
+ UINTN ProcessorVersionStrLen;
+ UINTN SerialNumberStrLen;
+ UINTN AssetTagStrLen;
+ UINTN PartNumberStrLen;
+ UINTN StringBufferSize;
+ UINTN TotalSize;
+
+ UINT8 Voltage;
+ UINT16 CoreCount;
+ UINT16 CoreEnabled;
+ UINT16 ThreadCount;
+ UINT16 CurrentSpeed;
+ PROCESSOR_STATUS_DATA ProcessorStatus = {{0}};
+ PROCESSOR_CHARACTERISTICS_DATA ProcessorCharacteristics = {{0}};
+
+ CHAR16 *CpuVersion;
+ STRING_REF TokenToUpdate;
+
+ UINT64 *ProcessorId;
+ Type4Record = NULL;
+ ProcessorManuStr = NULL;
+ ProcessorVersionStr = NULL;
+ SerialNumberStr = NULL;
+ AssetTagStr = NULL;
+ PartNumberStr = NULL;
+
+ if(OemIsSocketPresent(ProcessorNumber)) //CPU is present
+ {
+ Voltage = BIT7 | 9; // 0.9V
+
+ Status = AddSmbiosCacheTypeTable (ProcessorNumber, &L1CacheHandle, &L2CacheHandle, &L3CacheHandle);
+ if(EFI_ERROR(Status))
+ {
+ return Status;
+ }
+
+ CurrentSpeed = GetCpuFrequency(ProcessorNumber);
+
+ CoreCount = PlatformGetCoreCount();
+ CoreEnabled = CoreCount;
+ ThreadCount = CoreCount;
+
+ CpuVersion = (CHAR16 *) PcdGetPtr (PcdCPUInfo);
+ if (StrLen(CpuVersion) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_PROCESSOR_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, CpuVersion, NULL);
+ }
+
+ ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE);
+ ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION);
+ SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER);
+ AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG);
+ PartNumber = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER);
+
+ // Processor Status
+ ProcessorStatus.Bits.CpuStatus = 1; // CPU Enabled
+ ProcessorStatus.Bits.Reserved1 = 0;
+ ProcessorStatus.Bits.SocketPopulated = 1; // CPU Socket Populated
+ ProcessorStatus.Bits.Reserved2 = 0;
+
+ // Processor Characteristics
+ ProcessorCharacteristics.Bits.Reserved = 0;
+ ProcessorCharacteristics.Bits.Capable64Bit = 1; // 64-bit Capable
+ ProcessorCharacteristics.Bits.Unknown = 0;
+ ProcessorCharacteristics.Bits.EnhancedVirtualization = 1;
+ ProcessorCharacteristics.Bits.HardwareThread = 0;
+ ProcessorCharacteristics.Bits.MultiCore = 1;
+ ProcessorCharacteristics.Bits.ExecuteProtection = 1;
+ ProcessorCharacteristics.Bits.PowerPerformanceControl = 1;
+ ProcessorCharacteristics.Bits.Reserved2 = 0;
+ }
+ else
+ {
+ Voltage = 0;
+ CurrentSpeed = 0;
+ CoreCount = 0;
+ CoreEnabled = 0;
+ ThreadCount = 0;
+ L1CacheHandle = 0xFFFF;
+ L2CacheHandle = 0xFFFF;
+ L3CacheHandle = 0xFFFF;
+
+ ProcessorManu = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+ ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+ SerialNumber = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+ AssetTag = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+ PartNumber = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+ }
+
+ // Processor Socket Designation
+ StringBufferSize = sizeof(CHAR16) * SMBIOS_STRING_MAX_LENGTH;
+ ProcessorSocketStr = AllocateZeroPool(StringBufferSize);
+ if (ProcessorSocketStr == NULL)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, StringBufferSize, L"CPU%02d", ProcessorNumber + 1);
+
+ // Processor Manufacture
+ ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
+ ProcessorManuStrLen = StrLen (ProcessorManuStr);
+
+ // Processor Version
+ ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
+ ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
+
+ // Serial Number
+ SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
+ SerialNumberStrLen = StrLen (SerialNumberStr);
+
+ // Asset Tag
+ AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
+ AssetTagStrLen = StrLen (AssetTagStr);
+
+ // Part Number
+ PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
+ PartNumberStrLen = StrLen (PartNumberStr);
+
+ TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1 + AssetTagStrLen + 1 + PartNumberStrLen + 1 + 1;
+ Type4Record = AllocateZeroPool (TotalSize);
+ if (Type4Record == NULL)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(Type4Record, &mSmbiosProcessorTable[ProcessorNumber], sizeof (SMBIOS_TABLE_TYPE4));
+
+ *(UINT8 *) &Type4Record->Voltage = Voltage;
+ Type4Record->CurrentSpeed = CurrentSpeed;
+ Type4Record->Status = ProcessorStatus.Data;
+ Type4Record->L1CacheHandle = L1CacheHandle;
+ Type4Record->L2CacheHandle = L2CacheHandle;
+ Type4Record->L3CacheHandle = L3CacheHandle;
+ Type4Record->CoreCount = CoreCount;
+ Type4Record->EnabledCoreCount = CoreEnabled;
+ Type4Record->ThreadCount = ThreadCount;
+ Type4Record->ProcessorCharacteristics = ProcessorCharacteristics.Data;
+
+ Type4Record->ExternalClock = (UINT16)(ArmReadCntFrq() / 1000 / 1000);
+ ProcessorId = (UINT64 *)&(Type4Record->ProcessorId);
+ *ProcessorId = ArmReadMidr();
+
+ OptionalStrStart = (CHAR8 *) (Type4Record + 1);
+ UnicodeStrToAsciiStr (ProcessorSocketStr, OptionalStrStart);
+ UnicodeStrToAsciiStr (ProcessorManuStr, OptionalStrStart + ProcessorSocketStrLen + 1);
+ UnicodeStrToAsciiStr (ProcessorVersionStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1);
+ UnicodeStrToAsciiStr (SerialNumberStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1);
+ UnicodeStrToAsciiStr (AssetTagStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1);
+ UnicodeStrToAsciiStr (PartNumberStr, OptionalStrStart + ProcessorSocketStrLen + 1 + ProcessorManuStrLen + 1 + ProcessorVersionStrLen + 1 + SerialNumberStrLen + 1 + AssetTagStrLen + 1);
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type4Record);
+ if (EFI_ERROR (Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+ FreePool (Type4Record);
+
+Exit:
+ if(ProcessorSocketStr != NULL)
+ {
+ FreePool (ProcessorSocketStr);
+ }
+ if(ProcessorManuStr != NULL)
+ {
+ FreePool (ProcessorManuStr);
+ }
+ if(ProcessorVersionStr != NULL)
+ {
+ FreePool (ProcessorVersionStr);
+ }
+ if(SerialNumberStr != NULL)
+ {
+ FreePool (SerialNumberStr);
+ }
+ if(AssetTagStr != NULL)
+ {
+ FreePool (AssetTagStr);
+ }
+ if(PartNumberStr != NULL)
+ {
+ FreePool (PartNumberStr);
+ }
+
+ return Status;
+}
+
+/**
+ Standard EFI driver point. This driver locates the ProcessorConfigurationData Variable,
+ if it exists, add the related SMBIOS tables by PI SMBIOS protocol.
+
+ @param ImageHandle Handle for the image of this driver
+ @param SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The data was successfully stored.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessorSubClassEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SocketIndex;
+
+ //
+ // Locate dependent protocols
+ //
+ Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&mSmbios);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Add our default strings to the HII database. They will be modified later.
+ //
+ mHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ NULL,
+ ProcessorSubClassStrings,
+ NULL,
+ NULL
+ );
+ if (mHiiHandle == NULL)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Add SMBIOS tables for populated sockets.
+ //
+ for (SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++)
+ {
+ if((SocketIndex == 1) && !OemIsMpBoot())
+ {
+ break;
+ }
+ Status = AddSmbiosProcessorTypeTable (SocketIndex);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Add Processor Type Table Failed! %r.\n", Status));
+ return Status;
+ }
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h
new file mode 100644
index 0000000000..6ddc6cf590
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClass.h
@@ -0,0 +1,108 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _PROCESSOR_SUBCLASS_DRIVER_H
+#define _PROCESSOR_SUBCLASS_DRIVER_H
+
+#include <Uefi.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/HiiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include <PlatformArch.h>
+#include <Library/PlatformSysCtrlLib.h>
+#include <Library/OemMiscLib.h>
+#include <Library/ArmLib.h>
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+extern UINT8 ProcessorSubClassStrings[];
+
+#define CPU_CACHE_L1_Instruction 0
+#define CPU_CACHE_L1_Data 1
+#define CPU_CACHE_L2 2
+#define CPU_CACHE_L3 3
+#define MAX_CACHE_LEVEL 4
+
+#define EXTERNAL_CLOCK 50 //50 MHz
+#define CPU_MAX_SPEED 2100 //2.1G
+
+//
+// Cache Info
+//
+typedef struct {
+ UINT16 InstalledSize; //In KB
+ CACHE_TYPE_DATA SystemCacheType;
+ CACHE_ASSOCIATIVITY_DATA Associativity;
+} CACHE_INFO;
+
+//
+// Cache Configuration
+//
+typedef union {
+ struct {
+ UINT16 Level :3;
+ UINT16 Socketed :1;
+ UINT16 Reserved1 :1;
+ UINT16 Location :2;
+ UINT16 Enable :1;
+ UINT16 OperationalMode :2;
+ UINT16 Reserved2 :6;
+ } Bits;
+ UINT16 Data;
+}CACHE_CONFIGURATION;
+
+//
+// Processor Status
+//
+typedef union {
+ struct {
+ UINT8 CpuStatus :3; // Indicates the status of the processor.
+ UINT8 Reserved1 :3; // Reserved for future use. Should be set to zero.
+ UINT8 SocketPopulated :1; // Indicates if the processor socket is populated or not.
+ UINT8 Reserved2 :1; // Reserved for future use. Should be set to zero.
+ } Bits;
+ UINT8 Data;
+}PROCESSOR_STATUS_DATA;
+
+//
+// Processor Characteristics
+//
+typedef union {
+ struct {
+ UINT16 Reserved :1;
+ UINT16 Unknown :1;
+ UINT16 Capable64Bit :1;
+ UINT16 MultiCore :1;
+ UINT16 HardwareThread :1;
+ UINT16 ExecuteProtection :1;
+ UINT16 EnhancedVirtualization :1;
+ UINT16 PowerPerformanceControl :1;
+ UINT16 Reserved2 :8;
+ } Bits;
+ UINT16 Data;
+} PROCESSOR_CHARACTERISTICS_DATA;
+
+#endif
diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
new file mode 100644
index 0000000000..2275586ff3
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
@@ -0,0 +1,64 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ProcessorSubClass
+ FILE_GUID = 9B25B1EA-0FD4-455D-A450-AD640C8A9C1B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ProcessorSubClassEntryPoint
+
+[Sources]
+ ProcessorSubClassStrings.uni
+ ProcessorSubClass.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ IoLib
+ HiiLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ PrintLib
+ PcdLib
+
+ PlatformSysCtrlLib
+ OemMiscLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ gHisiTokenSpaceGuid.PcdCPUInfo
+ gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
+
+[Guids]
+
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
new file mode 100644
index 0000000000..d2928faf93
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
@@ -0,0 +1,32 @@
+///// @file
+//
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+// Copyright (c) 2015, Linaro Limited. All rights reserved.
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+/////
+
+/=#
+
+#langdef en-US "English"
+
+//
+// Processor Information
+//
+#string STR_PROCESSOR_SOCKET_DESIGNATION #language en-US "Hisilicon PhosphorV660 Processor"
+#string STR_PROCESSOR_MANUFACTURE #language en-US "Hisilicon"
+#string STR_PROCESSOR_VERSION #language en-US "Hi1610ES"
+#string STR_PROCESSOR_SERIAL_NUMBER #language en-US "To be filled by O.E.M."
+#string STR_PROCESSOR_ASSET_TAG #language en-US "To be filled by O.E.M."
+#string STR_PROCESSOR_PART_NUMBER #language en-US "To be filled by O.E.M."
+#string STR_PROCESSOR_UNKNOWN #language en-US "Unknown"
+
+
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h
new file mode 100644
index 0000000000..66f9db9665
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMisc.h
@@ -0,0 +1,226 @@
+/**@file
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SmbiosMisc.h
+
+Abstract:
+
+ Header file for the SmbiosMisc Driver.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#ifndef _SMBIOS_MISC_DRIVER_H
+#define _SMBIOS_MISC_DRIVER_H
+
+#include <FrameworkDxe.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/DebugMask.h>
+
+#include <Library/PrintLib.h>
+
+//
+// Data table entry update function.
+//
+typedef EFI_STATUS (EFIAPI EFI_MISC_SMBIOS_DATA_FUNCTION) (
+ IN VOID *RecordData,
+ IN EFI_SMBIOS_PROTOCOL *Smbios
+ );
+
+
+//
+// Data table entry definition.
+//
+typedef struct {
+ //
+ // intermediat input data for SMBIOS record
+ //
+ VOID *RecordData;
+ EFI_MISC_SMBIOS_DATA_FUNCTION *Function;
+} EFI_MISC_SMBIOS_DATA_TABLE;
+
+
+//
+// Data Table extern definitions.
+//
+#define MISC_SMBIOS_TABLE_EXTERNS(NAME1, NAME2, NAME3) \
+extern NAME1 NAME2 ## Data; \
+extern EFI_MISC_SMBIOS_DATA_FUNCTION NAME3 ## Function;
+
+
+//
+// Data Table entries
+//
+
+#define MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(NAME1, NAME2) \
+{ \
+ & NAME1 ## Data, \
+ NAME2 ## Function \
+}
+
+
+//
+// Global definition macros.
+//
+#define MISC_SMBIOS_TABLE_DATA(NAME1, NAME2) \
+ NAME1 NAME2 ## Data
+
+#define MISC_SMBIOS_TABLE_FUNCTION(NAME2) \
+ EFI_STATUS EFIAPI NAME2 ## Function( \
+ IN VOID *RecordData, \
+ IN EFI_SMBIOS_PROTOCOL *Smbios \
+ )
+
+//
+// Data Table Array Entries
+//
+extern EFI_HII_HANDLE mHiiHandle;
+
+typedef struct _EFI_TYPE11_OEM_STRING{
+ UINT8 Offset;
+ EFI_STRING_ID RefOemDefineString;
+} EFI_TYPE11_OEM_STRING;
+
+typedef struct _EFI_TYPE12_SYSTEM_CONFIGURATION_OPTIONS_STRING{
+ UINT8 Offset;
+ EFI_STRING_ID RefType12SystemConfigurationOptionsString;
+} EFI_TYPE12_SYSTEM_CONFIGURATION_OPTIONS_STRING;
+
+typedef struct _EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING{
+ UINT8 *LanguageSignature;
+ EFI_STRING_ID InstallableLanguageLongString;
+ EFI_STRING_ID InstallableLanguageAbbreviateString;
+} EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING;
+
+typedef struct _EFI_TYPE40_ADDITIONAL_INFORMATION_ENTRY{
+ UINT8 RefType;
+ UINT8 RefOffset;
+ EFI_STRING_ID RefString;
+ UINT8 Value;
+} EFI_TYPE40_ADDITIONAL_INFORMATION_ENTRY;
+
+typedef enum {
+ STRING,
+ DATA,
+} OEM_DEFINE_TYPE;
+
+typedef struct {
+ OEM_DEFINE_TYPE Type;
+ UINTN Token;
+ UINTN DataSize;
+} OEM_DEFINE_INFO_STRING;
+
+typedef struct {
+ OEM_DEFINE_TYPE Type;
+ UINTN DataAddress;
+ UINTN DataSize;
+} OEM_DEFINE_INFO_DATA;
+
+typedef union {
+ OEM_DEFINE_INFO_STRING DefineString;
+ OEM_DEFINE_INFO_DATA DefineData;
+} EFI_OEM_DEFINE_ARRAY;
+
+typedef struct _DMI_STRING_STRUCTURE {
+ UINT8 Type;
+ UINT8 Offset;
+ UINT8 Valid;
+ UINT16 Length;
+ UINT8 String[1]; // Variable length field
+} DMI_STRING_STRUCTURE;
+
+typedef struct {
+ UINT8 Type; // The SMBIOS structure type
+ UINT8 FixedOffset; // The offset of the string reference
+ // within the structure's fixed data.
+} DMI_UPDATABLE_STRING;
+
+EFI_STATUS
+FindString (
+ IN UINT8 Type,
+ IN UINT8 Offset,
+ IN EFI_STRING_ID TokenToUpdate
+);
+
+EFI_STATUS
+FindUuid (
+ EFI_GUID *Uuid
+);
+
+EFI_STATUS
+StringToBiosVeriosn (
+ IN EFI_STRING_ID BiosVersionToken,
+ OUT UINT8 *MajorVersion,
+ OUT UINT8 *MinorVersion
+);
+
+
+/**
+ Logs SMBIOS record.
+
+ @param [in] Buffer Pointer to the data buffer.
+ @param [in] SmbiosHandle Pointer for retrieve handle.
+
+**/
+EFI_STATUS
+LogSmbiosData (
+ IN UINT8 *Buffer,
+ IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle
+ );
+
+/**
+ Get Link Type Handle.
+
+ @param [in] SmbiosType Get this Type from SMBIOS table
+ @param [out] HandleArray Pointer to Hadndler array with has been free by caller
+ @param [out] HandleCount Pointer to Hadndler Counter
+
+**/
+VOID
+GetLinkTypeHandle(
+ IN UINT8 SmbiosType,
+ OUT UINT16 **HandleArray,
+ OUT UINTN *HandleCount
+ );
+
+typedef enum {
+ ProductNameType01,
+ SerialNumType01,
+ UuidType01,
+ SystemManufacturerType01,
+ AssertTagType02,
+ SrNumType02,
+ BoardManufacturerType02,
+ AssetTagType03,
+ SrNumType03,
+ VersionType03,
+ ChassisTypeType03 ,
+ ManufacturerType03,
+} GET_INFO_BMC_OFFSET;
+
+VOID UpdateSmbiosInfo (IN EFI_HII_HANDLE mHiiHandle, IN EFI_STRING_ID TokenToUpdate, IN UINT8 Offset);
+EFI_STATUS GetUuidType1 (IN OUT EFI_GUID *Uuid);
+EFI_STATUS IpmiGetChassisType (IN OUT UINT8 *Type);
+#endif
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
new file mode 100644
index 0000000000..8e00865712
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
@@ -0,0 +1,58 @@
+/**@file
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SmbiosMiscDataTable.c
+
+Abstract:
+
+ This file provide OEM to config SMBIOS Misc Type.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE0, MiscBiosVendor, MiscBiosVendor)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE1, MiscSystemManufacturer, MiscSystemManufacturer)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE3, MiscChassisManufacturer, MiscChassisManufacturer)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE2, MiscBaseBoardManufacturer, MiscBaseBoardManufacturer)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE13, MiscNumberOfInstallableLanguages, MiscNumberOfInstallableLanguages)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE32, MiscBootInformation, MiscBootInformation)
+ MISC_SMBIOS_TABLE_EXTERNS(SMBIOS_TABLE_TYPE38, MiscIpmiDeviceInformation, MiscIpmiDeviceInformation)
+
+
+EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[] = {
+ // Type0
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBiosVendor, MiscBiosVendor),
+ // Type1
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemManufacturer, MiscSystemManufacturer),
+ // Type3
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscChassisManufacturer, MiscChassisManufacturer),
+ // Type2
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBaseBoardManufacturer, MiscBaseBoardManufacturer),
+ // Type13
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscNumberOfInstallableLanguages, MiscNumberOfInstallableLanguages),
+ // Type32
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscBootInformation, MiscBootInformation),
+ // Type38
+ MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscIpmiDeviceInformation, MiscIpmiDeviceInformation),
+};
+
+
+//
+// Number of Data Table entries.
+//
+UINTN mSmbiosMiscDataTableEntries =
+ (sizeof mSmbiosMiscDataTable) / sizeof(EFI_MISC_SMBIOS_DATA_TABLE);
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
new file mode 100644
index 0000000000..61cead7779
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
@@ -0,0 +1,108 @@
+## @file
+# Component description file for SmbiosMisc instance.
+#
+# Parses the MiscSubclassDataTable and reports any generated data to the DataHub.
+# All .uni file who tagged with "ToolCode="DUMMY"" in following file list is included by
+# MiscSubclassDriver.uni file, the StrGather tool will expand MiscSubclassDriver.uni file
+# and parse all .uni file.
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+# Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+# Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmbiosMiscDxe
+ FILE_GUID = EF0C99B6-B1D3-4025-9405-BF6A560FE0E0
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SmbiosMiscEntryPoint
+
+[Sources]
+ SmbiosMisc.h
+ SmbiosMiscDataTable.c
+ SmbiosMiscEntryPoint.c
+ SmbiosMiscLibString.uni
+ ./Type00/MiscBiosVendorData.c
+ ./Type00/MiscBiosVendorFunction.c
+ ./Type01/MiscSystemManufacturerData.c
+ ./Type01/MiscSystemManufacturerFunction.c
+ ./Type02/MiscBaseBoardManufacturerData.c
+ ./Type02/MiscBaseBoardManufacturerFunction.c
+ ./Type03/MiscChassisManufacturerData.c
+ ./Type03/MiscChassisManufacturerFunction.c
+ ./Type13/MiscNumberOfInstallableLanguagesData.c
+ ./Type13/MiscNumberOfInstallableLanguagesFunction.c
+ ./Type32/MiscBootInformationData.c
+ ./Type32/MiscBootInformationFunction.c
+ ./Type38/MiscIpmiDeviceInformationData.c
+ ./Type38/MiscIpmiDeviceInformationFunction.c
+
+ ./Type09/MiscSystemSlotDesignationData.c
+ ./Type09/MiscSystemSlotDesignationFunction.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ HiiLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ HobLib
+
+ IpmiCmdLib
+
+ SerdesLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdFdSize
+ gHisiTokenSpaceGuid.PcdFirmwareVendor
+ gHisiTokenSpaceGuid.PcdBiosVersionString
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareReleaseDateString
+
+ gHisiTokenSpaceGuid.PcdSystemProductName
+ gHisiTokenSpaceGuid.PcdSystemVersion
+ gHisiTokenSpaceGuid.PcdBaseBoardProductName
+ gHisiTokenSpaceGuid.PcdBaseBoardVersion
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+
+ gHisiTokenSpaceGuid.PcdBiosVersionForBmc
+
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
+
+[Guids]
+ gEfiGenericVariableGuid
+ gVersionInfoHobGuid
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
new file mode 100644
index 0000000000..051410b527
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
@@ -0,0 +1,194 @@
+/**@file
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SmbiosMiscEntryPoint.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data using SMBIOS protocol.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+#define MAX_HANDLE_COUNT 0x10
+
+EFI_HANDLE mImageHandle;
+EFI_HII_HANDLE mHiiHandle;
+EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
+
+//
+// Data Table Array
+//
+extern EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[];
+//
+// Data Table Array Entries
+//
+extern UINTN mSmbiosMiscDataTableEntries;
+
+extern UINT8 SmbiosMiscDxeStrings[];
+
+
+
+/**
+ Standard EFI driver point. This driver parses the mSmbiosMiscDataTable
+ structure and reports any generated data using SMBIOS protocol.
+
+ @param ImageHandle Handle for the image of this driver
+ @param SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The data was successfully stored.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosMiscEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN Index;
+ EFI_STATUS EfiStatus;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+
+ mImageHandle = ImageHandle;
+
+ EfiStatus = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+ if (EFI_ERROR(EfiStatus))
+ {
+ DEBUG((EFI_D_ERROR, "Could not locate SMBIOS protocol. %r\n", EfiStatus));
+ return EfiStatus;
+ }
+
+ mSmbios = Smbios;
+
+ mHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ mImageHandle,
+ SmbiosMiscDxeStrings,
+ NULL
+ );
+ if(mHiiHandle == NULL)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < mSmbiosMiscDataTableEntries; ++Index)
+ {
+ //
+ // If the entry have a function pointer, just log the data.
+ //
+ if (mSmbiosMiscDataTable[Index].Function != NULL)
+ {
+ EfiStatus = (*mSmbiosMiscDataTable[Index].Function)(
+ mSmbiosMiscDataTable[Index].RecordData,
+ Smbios
+ );
+
+ if (EFI_ERROR(EfiStatus))
+ {
+ DEBUG((EFI_D_ERROR, "Misc smbios store error. Index=%d, ReturnStatus=%r\n", Index, EfiStatus));
+ return EfiStatus;
+ }
+ }
+ }
+
+ return EfiStatus;
+}
+
+
+/**
+ Logs SMBIOS record.
+
+ @param Buffer The data for the fixed portion of the SMBIOS record. The format of the record is
+ determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined
+ by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or
+ a set of null terminated strings and a null.
+ @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.
+
+ @retval EFI_SUCCESS Record was added.
+ @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.
+
+**/
+EFI_STATUS
+LogSmbiosData (
+ IN UINT8 *Buffer,
+ IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle
+ )
+{
+ EFI_STATUS Status;
+
+ *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+
+ Status = mSmbios->Add (
+ mSmbios,
+ NULL,
+ SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER *)Buffer
+ );
+
+ return Status;
+}
+
+
+VOID
+GetLinkTypeHandle(
+ IN UINT8 SmbiosType,
+ OUT UINT16 **HandleArray,
+ OUT UINTN *HandleCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *LinkTypeData = NULL;
+
+ if(mSmbios == NULL)
+ return ;
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+
+ *HandleArray = AllocateZeroPool(sizeof(UINT16) * MAX_HANDLE_COUNT);
+ if (*HandleArray == NULL)
+ {
+ DEBUG ((EFI_D_INFO, "HandleArray allocate memory resource failed.\n"));
+ return;
+ }
+
+ *HandleCount = 0;
+
+ while(1)
+ {
+ Status = mSmbios->GetNext(
+ mSmbios,
+ &SmbiosHandle,
+ &SmbiosType,
+ &LinkTypeData,
+ NULL
+ );
+
+ if(!EFI_ERROR(Status))
+ {
+ (*HandleArray)[*HandleCount] = LinkTypeData->Handle;
+ (*HandleCount)++;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni
new file mode 100644
index 0000000000..2e434e323a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/SmbiosMiscLibString.uni
@@ -0,0 +1,28 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+
+/=#
+
+#langdef en-US "English"
+
+#include "./Type00/MiscBiosVendor.uni"
+#include "./Type01/MiscSystemManufacturer.uni"
+#include "./Type02/MiscBaseBoardManufacturer.uni"
+#include "./Type03/MiscChassisManufacturer.uni"
+#include "./Type13/MiscNumberOfInstallableLanguages.uni"
+#include "./Type09/MiscSystemSlotDesignation.uni"
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
new file mode 100644
index 0000000000..215952a560
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
@@ -0,0 +1,25 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+/=#
+
+//#string STR_MISC_BIOS_VENDOR #language en-US "Bios Vendor"
+#string STR_MISC_BIOS_VERSION #language en-US "Bios Version"
+//#string STR_MISC_BIOS_RELEASE_DATE #language en-US "Bios Release Date"
+
+#string STR_MISC_BIOS_VENDOR #language en-US "Huawei Technologies Co., Ltd."
+#string STR_MISC_BIOS_RELEASE_DATE #language en-US "01/01/1900"
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
new file mode 100644
index 0000000000..b822768b44
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscBiosVendorData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type0 Data
+
+Based on the files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+**/
+
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE0, MiscBiosVendor) = {
+ { //Hdr
+ EFI_SMBIOS_TYPE_BIOS_INFORMATION, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, //Vendor
+ 2, //BiosVersion
+ 0xE000, //BiosSegment
+ 3, //BiosReleaseDate
+ 0, //BiosSize
+ { //BiosCharacteristics
+ 0, // Reserved :2
+ 0, // Unknown :1
+ 0, // BiosCharacteristicsNotSupported :1
+ 0, // IsaIsSupported :1
+ 0, // McaIsSupported :1
+ 0, // EisaIsSupported :1
+ 1, // PciIsSupported :1
+ 0, // PcmciaIsSupported :1
+ 0, // PlugAndPlayIsSupported :1
+ 0, // ApmIsSupported :1
+ 1, // BiosIsUpgradable :1
+ 1, // BiosShadowingAllowed :1
+ 0, // VlVesaIsSupported :1
+ 0, // EscdSupportIsAvailable :1
+ 1, // BootFromCdIsSupported :1
+ 1, // SelectableBootIsSupported :1
+ 0, // RomBiosIsSocketed :1
+ 0, // BootFromPcmciaIsSupported :1
+ 1, // EDDSpecificationIsSupported :1
+ 1, // JapaneseNecFloppyIsSupported :1
+ 1, // JapaneseToshibaFloppyIsSupported :1
+ 1, // Floppy525_360IsSupported :1
+ 1, // Floppy525_12IsSupported :1
+ 1, // Floppy35_720IsSupported :1
+ 1, // Floppy35_288IsSupported :1
+ 0, // PrintScreenIsSupported :1
+ 1, // Keyboard8042IsSupported :1
+ 0, // SerialIsSupported :1
+ 0, // PrinterIsSupported :1
+ 1, // CgaMonoIsSupported :1
+ 0, // NecPc98 :1
+ 0 // ReservedForVendor :32
+ },
+
+ {
+ 0x03, //BIOSCharacteristicsExtensionBytes[0]
+ // { //BiosReserved
+ // 1, // AcpiIsSupported :1
+ // 1, // UsbLegacyIsSupported :1
+ // 0, // AgpIsSupported :1
+ // 0, // I20BootIsSupported :1
+ // 0, // Ls120BootIsSupported :1
+ // 0, // AtapiZipDriveBootIsSupported :1
+ // 0, // Boot1394IsSupported :1
+ // 0 // SmartBatteryIsSupported :1
+ // },
+ 0x0D //BIOSCharacteristicsExtensionBytes[1]
+ // { //SystemReserved
+ // 1, //BiosBootSpecIsSupported :1
+ // 0, //FunctionKeyNetworkBootIsSupported :1
+ // 1, //TargetContentDistributionEnabled :1
+ // 1, //UefiSpecificationSupported :1
+ // 0, //VirtualMachineSupported :1
+ // 0 //ExtensionByte2Reserved :3
+ // },
+ },
+ 0, //SystemBiosMajorRelease;
+ 0, //SystemBiosMinorRelease;
+ 0xFF, //EmbeddedControllerFirmwareMajorRelease;
+ 0xFF //EmbeddedControllerFirmwareMinorRelease;
+};
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
new file mode 100644
index 0000000000..9a42f04085
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
@@ -0,0 +1,258 @@
+/** @file
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+ Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ MiscBiosVendorData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to the DataHub.
+
+Based on the files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+--*/
+
+//
+#include "SmbiosMisc.h"
+#include <Library/HobLib.h>
+#include <Guid/VersionInfoHobGuid.h>
+
+
+/**
+ Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
+ as the unit.
+
+ @param Value Pointer to Base2_Data
+
+ @retval
+
+**/
+UINT8
+Base2ToByteWith64KUnit (
+ IN UINTN Value
+ )
+{
+ UINT8 Size;
+
+ Size = Value / SIZE_64KB + (Value % SIZE_64KB + SIZE_64KB - 1) / SIZE_64KB;
+
+ return Size;
+}
+
+
+/**
+
+**/
+VOID *
+GetBiosReleaseDate (
+ )
+{
+ CHAR16 *ReleaseDate = NULL;
+ VERSION_INFO *Version;
+ VOID *Hob;
+
+ ReleaseDate = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+ if(NULL == ReleaseDate)
+ {
+ return NULL;
+ }
+
+ Hob = GetFirstGuidHob (&gVersionInfoHobGuid);
+ if (Hob == NULL) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] Version info HOB not found!\n", __FUNCTION__, __LINE__));
+ return NULL;
+ }
+
+ Version = GET_GUID_HOB_DATA (Hob);
+ (VOID)UnicodeSPrintAsciiFormat( ReleaseDate,
+ (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH,
+ "%02d/%02d/%4d",
+ Version->BuildTime.Month,
+ Version->BuildTime.Day,
+ Version->BuildTime.Year
+ );
+
+ return ReleaseDate;
+}
+
+VOID *
+GetBiosVersion (
+ )
+{
+ VERSION_INFO *Version;
+ VOID *Hob;
+
+ Hob = GetFirstGuidHob (&gVersionInfoHobGuid);
+ if (Hob == NULL) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] Version info HOB not found!\n", __FUNCTION__, __LINE__));
+ return NULL;
+ }
+ Version = GET_GUID_HOB_DATA (Hob);
+ return Version->String;
+}
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscBiosVendor (Type 0).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscBiosVendor)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN VendorStrLen;
+ UINTN VerStrLen;
+ UINTN DateStrLen;
+ UINTN BiosPhysicalSizeHexValue;
+ CHAR16 *Vendor;
+ CHAR16 *Version;
+ CHAR16 *ReleaseDate;
+ CHAR16 *Char16String;
+ EFI_STATUS Status;
+ STRING_REF TokenToUpdate;
+ STRING_REF TokenToGet;
+ SMBIOS_TABLE_TYPE0 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE0 *InputData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE0 *)RecordData;
+
+ Vendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);
+ if (StrLen(Vendor) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+ HiiSetString (mHiiHandle, TokenToUpdate, Vendor, NULL);
+ }
+
+ Version = GetBiosVersion();
+ if (StrLen (Version) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ else
+ {
+ Version = (CHAR16 *) PcdGetPtr (PcdBiosVersionForBmc);
+ if (StrLen (Version) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ else
+ {
+ Version = (CHAR16 *) PcdGetPtr (PcdBiosVersionString);
+ if (StrLen (Version) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+ }
+ }
+
+ Char16String = GetBiosReleaseDate ();
+ if (StrLen(Char16String) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+ HiiSetString (mHiiHandle, TokenToUpdate, Char16String, NULL);
+ }
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+ Vendor = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VendorStrLen = StrLen(Vendor);
+
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+ Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(Version);
+
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+ ReleaseDate = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ DateStrLen = StrLen(ReleaseDate);
+
+ //
+ // Now update the BiosPhysicalSize
+ //
+ BiosPhysicalSizeHexValue = FixedPcdGet32 (PcdFdSize);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);
+ if(NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE0));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);
+ SmbiosRecord->BiosSegment = (UINT16)(FixedPcdGet32 (PcdFdBaseAddress) / 0x10000);
+ SmbiosRecord->BiosSize = Base2ToByteWith64KUnit(BiosPhysicalSizeHexValue) - 1;
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(Vendor, OptionalStrStart);
+ UnicodeStrToAsciiStr(Version, OptionalStrStart + VendorStrLen + 1);
+ UnicodeStrToAsciiStr(ReleaseDate, OptionalStrStart + VendorStrLen + 1 + VerStrLen + 1);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type00 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+
+Exit:
+ if(Vendor != NULL)
+ {
+ FreePool(Vendor);
+ }
+
+ if(Version != NULL)
+ {
+ FreePool(Version);
+ }
+
+ if(ReleaseDate != NULL)
+ {
+ FreePool(ReleaseDate);
+ }
+
+ if(Char16String != NULL)
+ {
+ FreePool(Char16String);
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
new file mode 100644
index 0000000000..1632f83880
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
@@ -0,0 +1,27 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+/=#
+
+#string STR_MISC_SYSTEM_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd."
+//#string STR_MISC_SYSTEM_PRODUCT_NAME #language en-US "To be filled by O.E.M."
+#string STR_MISC_SYSTEM_PRODUCT_NAME #language en-US "PANGEA"
+//#string STR_MISC_SYSTEM_VERSION #language en-US "To be filled by O.E.M."
+#string STR_MISC_SYSTEM_VERSION #language en-US "V200R002"
+#string STR_MISC_SYSTEM_SERIAL_NUMBER #language en-US "To be filled by O.E.M."
+#string STR_MISC_SYSTEM_SKU_NUMBER #language en-US "To be filled by O.E.M."
+#string STR_MISC_SYSTEM_FAMILY #language en-US "To be filled by O.E.M."
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
new file mode 100644
index 0000000000..37fc33b00a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
@@ -0,0 +1,52 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscSystemManufacturerData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type1 Data
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+**/
+
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) System Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE1, MiscSystemManufacturer) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // Manufacturer
+ 2, // ProductName
+ 3, // Version
+ 4, // SerialNumber
+ { // Uuid
+ 0x12345678, 0x1234, 0x5678, {0x90, 0xab, 0xcd, 0xde, 0xef, 0xaa, 0xbb, 0xcc}
+ },
+ SystemWakeupTypePowerSwitch, // SystemWakeupType
+ 5, // SKUNumber,
+ 6 // Family
+};
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
new file mode 100644
index 0000000000..fcefe2442c
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
@@ -0,0 +1,195 @@
+/*++
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscSystemManufacturerFunction.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+**/
+
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscSystemManufacturer (Type 1).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscSystemManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN VerStrLen;
+ UINTN PdNameStrLen;
+ UINTN SerialNumStrLen;
+ UINTN SKUNumStrLen;
+ UINTN FamilyStrLen;
+ EFI_STRING Manufacturer;
+ EFI_STRING ProductName;
+ EFI_STRING Version;
+ EFI_STRING SerialNumber;
+ EFI_STRING SKUNumber;
+ EFI_STRING Family;
+ STRING_REF TokenToGet;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE1 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE1 *InputData;
+ EFI_STATUS Status;
+ STRING_REF TokenToUpdate;
+ CHAR16 *Product;
+ CHAR16 *pVersion;
+
+ EFI_GUID Uuid;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE1 *)RecordData;
+
+ Product = (CHAR16 *) PcdGetPtr (PcdSystemProductName);
+ if (StrLen(Product) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+ HiiSetString (mHiiHandle, TokenToUpdate, Product, NULL);
+ }
+
+ pVersion = (CHAR16 *) PcdGetPtr (PcdSystemVersion);
+ if (StrLen(pVersion) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, pVersion, NULL);
+ }
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME), ProductNameType01);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER), SerialNumType01);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER), SystemManufacturerType01);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER);
+ Manufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(Manufacturer);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+ ProductName = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ PdNameStrLen = StrLen(ProductName);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+ Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(Version);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER);
+ SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumber);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER);
+ SKUNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SKUNumStrLen = StrLen(SKUNumber);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY);
+ Family = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ FamilyStrLen = StrLen(Family);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1
+ + PdNameStrLen + 1
+ + VerStrLen + 1
+ + SerialNumStrLen + 1
+ + SKUNumStrLen + 1
+ + FamilyStrLen + 1 + 1);
+
+ if (NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE1));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE1);
+
+ SmbiosRecord->Uuid = InputData->Uuid;
+ Status = GetUuidType1 (&Uuid);
+ if (!EFI_ERROR (Status))
+ {
+ SmbiosRecord->Uuid = Uuid;
+ }
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart);
+ UnicodeStrToAsciiStr(ProductName, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(SKUNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1);
+ UnicodeStrToAsciiStr(Family, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SKUNumStrLen + 1);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type01 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+
+Exit:
+ if(Manufacturer != NULL)
+ {
+ FreePool(Manufacturer);
+ }
+
+ if(ProductName != NULL)
+ {
+ FreePool(ProductName);
+ }
+
+ if(Version != NULL)
+ {
+ FreePool(Version);
+ }
+
+ if(SerialNumber != NULL)
+ {
+ FreePool(SerialNumber);
+ }
+
+ if(SKUNumber != NULL)
+ {
+ FreePool(SKUNumber);
+ }
+
+ if(Family != NULL)
+ {
+ FreePool(Family);
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
new file mode 100644
index 0000000000..11320c0fe7
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
@@ -0,0 +1,27 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+/=#
+
+#string STR_MISC_BASE_BOARD_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd."
+//#string STR_MISC_BASE_BOARD_PRODUCT_NAME #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_BASE_BOARD_PRODUCT_NAME #language en-US "STL2SPCA"
+//#string STR_MISC_BASE_BOARD_VERSION #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_BASE_BOARD_VERSION #language en-US "V200R002"
+#string STR_MISC_BASE_BOARD_SERIAL_NUMBER #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_BASE_BOARD_ASSET_TAG #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_BASE_BOARD_CHASSIS_LOCATION #language en-US "To Be Filled By O.E.M."
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
new file mode 100644
index 0000000000..20991b1ea1
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscBaseBoardManufacturerData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type2 Data
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Chassis Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE2, MiscBaseBoardManufacturer) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // BaseBoardManufacturer
+ 2, // BaseBoardProductName
+ 3, // BaseBoardVersion
+ 4, // BaseBoardSerialNumber
+ 5, // BaseBoardAssetTag
+ { // FeatureFlag
+ 1, // Motherboard :1
+ 0, // RequiresDaughterCard :1
+ 0, // Removable :1
+ 1, // Replaceable :1
+ 0, // HotSwappable :1
+ 0 // Reserved :3
+ },
+ 6, // BaseBoardChassisLocation
+ 0, // ChassisHandle;
+ BaseBoardTypeMotherBoard, // BoardType;
+ 0, // NumberOfContainedObjectHandles;
+ {
+ 0
+ } // ContainedObjectHandles[1];
+};
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
new file mode 100644
index 0000000000..a141f9e7d7
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
@@ -0,0 +1,198 @@
+/** @file
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+ Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscBaseBoardManufacturerFunction.c
+
+Abstract:
+
+ This driver parses the mSmbiosMiscDataTable structure and reports
+ any generated data using SMBIOS protocol.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+
+/**
+ This function makes basic board manufacturer to the contents of the
+ Misc Base Board Manufacturer (Type 2).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscBaseBoardManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN ProductNameStrLen;
+ UINTN VerStrLen;
+ UINTN SerialNumStrLen;
+ UINTN AssetTagStrLen;
+ UINTN ChassisLocaStrLen;
+ UINTN HandleCount = 0;
+ UINT16 *HandleArray = NULL;
+ CHAR16 *BaseBoardManufacturer;
+ CHAR16 *BaseBoardProductName;
+ CHAR16 *Version;
+ EFI_STRING SerialNumber;
+ EFI_STRING AssetTag;
+ EFI_STRING ChassisLocation;
+ STRING_REF TokenToGet;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE2 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE2 *InputData = NULL;
+ EFI_STATUS Status;
+
+ STRING_REF TokenToUpdate;
+ //CHAR16 *ProductName;
+ //CHAR16 *pVersion;
+ //uniBIOS_y00216284_018_end 2015-1-13 09:08:22
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE2*)RecordData;
+
+ BaseBoardProductName = (CHAR16 *) PcdGetPtr (PcdBaseBoardProductName);
+ if (StrLen(BaseBoardProductName) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+ HiiSetString (mHiiHandle, TokenToUpdate, BaseBoardProductName, NULL);
+ }
+
+ Version = (CHAR16 *) PcdGetPtr (PcdBaseBoardVersion);
+ if (StrLen(Version) > 0)
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION);
+ HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+ }
+
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG), AssertTagType02);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER), SrNumType02);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER), BoardManufacturerType02);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER);
+ BaseBoardManufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(BaseBoardManufacturer);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+ BaseBoardProductName = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ProductNameStrLen = StrLen(BaseBoardProductName);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION);
+ Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(Version);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER);
+ SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumber);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG);
+ AssetTag = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ AssetTagStrLen = StrLen(AssetTag);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_CHASSIS_LOCATION);
+ ChassisLocation = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ChassisLocaStrLen = StrLen(ChassisLocation);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE2) + ManuStrLen + 1
+ + ProductNameStrLen + 1
+ + VerStrLen + 1
+ + SerialNumStrLen + 1
+ + AssetTagStrLen + 1
+ + ChassisLocaStrLen + 1 + 1);
+ if (NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE2));
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE2);
+
+ //
+ // Update Contained objects Handle
+ //
+ SmbiosRecord->NumberOfContainedObjectHandles = 0;
+ GetLinkTypeHandle(EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, &HandleArray, &HandleCount);
+ if(HandleCount)
+ {
+ SmbiosRecord->ChassisHandle = HandleArray[0];
+ }
+
+ FreePool(HandleArray);
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(BaseBoardManufacturer, OptionalStrStart);
+ UnicodeStrToAsciiStr(BaseBoardProductName, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 );
+ UnicodeStrToAsciiStr(ChassisLocation, OptionalStrStart + ManuStrLen + 1 + ProductNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssetTagStrLen + 1);
+
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type02 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+
+Exit:
+ if(BaseBoardManufacturer != NULL)
+ {
+ FreePool(BaseBoardManufacturer);
+ }
+
+ if(BaseBoardProductName != NULL)
+ {
+ FreePool(BaseBoardProductName);
+ }
+
+ if(Version != NULL)
+ {
+ FreePool(Version);
+ }
+
+ if(SerialNumber != NULL)
+ {
+ FreePool(SerialNumber);
+ }
+
+ if(AssetTag != NULL)
+ {
+ FreePool(AssetTag);
+ }
+
+ if(ChassisLocation != NULL)
+ {
+ FreePool(ChassisLocation);
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
new file mode 100644
index 0000000000..543ef00c0d
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
@@ -0,0 +1,24 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+/=#
+
+#string STR_MISC_CHASSIS_MANUFACTURER #language en-US "Huawei Technologies Co., Ltd."
+#string STR_MISC_CHASSIS_VERSION #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_CHASSIS_SERIAL_NUMBER #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_CHASSIS_ASSET_TAG #language en-US "To Be Filled By O.E.M."
+#string STR_MISC_CHASSIS_SKU_NUMBER #language en-US "To Be Filled By O.E.M."
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
new file mode 100644
index 0000000000..6237fbe535
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscChassisManufacturerData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type3 Data
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Chassis Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE3, MiscChassisManufacturer) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE , // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // Manufactrurer
+ MiscChassisTypeMainServerChassis, // Type
+ 2, // Version
+ 3, // SerialNumber
+ 4, // AssetTag
+ ChassisStateSafe, // BootupState
+ ChassisStateSafe, // PowerSupplyState
+ ChassisStateSafe, // ThermalState
+ ChassisSecurityStatusNone, // SecurityState
+ {
+ 0, // OemDefined[0]
+ 0, // OemDefined[1]
+ 0, // OemDefined[2]
+ 0 // OemDefined[3]
+ },
+ 2, // Height
+ 1, // NumberofPowerCords
+ 0, // ContainedElementCount
+ 0, // ContainedElementRecordLength
+ { // ContainedElements[0]
+ {
+ 0, // ContainedElementType
+ 0, // ContainedElementMinimum
+ 0 // ContainedElementMaximum
+ }
+ }
+};
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
new file mode 100644
index 0000000000..4bb170117d
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
@@ -0,0 +1,199 @@
+/** @file
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscChassisManufacturerFunction.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+UINT8
+GetChassisType (
+)
+{
+ EFI_STATUS Status;
+ UINT8 ChassisType;
+ Status = IpmiGetChassisType(&ChassisType);
+ if (EFI_ERROR(Status))
+ {
+ return 0;
+ }
+
+ return ChassisType;
+}
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscChassisManufacturer (Type 3).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscChassisManufacturer)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN ManuStrLen;
+ UINTN VerStrLen;
+ UINTN AssertTagStrLen;
+ UINTN SerialNumStrLen;
+ UINTN ChaNumStrLen;
+ EFI_STRING Manufacturer;
+ EFI_STRING Version;
+ EFI_STRING SerialNumber;
+ EFI_STRING AssertTag;
+ EFI_STRING ChassisSkuNumber;
+ STRING_REF TokenToGet;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE3 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE3 *InputData;
+ EFI_STATUS Status;
+
+ UINT8 ContainedElementCount;
+ CONTAINED_ELEMENT ContainedElements = {0};
+ UINT8 ExtendLength = 0;
+
+ UINT8 ChassisType;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE3 *)RecordData;
+
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG), AssetTagType03);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER), SrNumType03);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_VERSION), VersionType03);
+ UpdateSmbiosInfo(mHiiHandle, STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER), ManufacturerType03);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER);
+ Manufacturer = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ManuStrLen = StrLen(Manufacturer);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_VERSION);
+ Version = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ VerStrLen = StrLen(Version);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER);
+ SerialNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SerialNumStrLen = StrLen(SerialNumber);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG);
+ AssertTag = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ AssertTagStrLen = StrLen(AssertTag);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SKU_NUMBER);
+ ChassisSkuNumber = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ ChaNumStrLen = StrLen(ChassisSkuNumber);
+
+ ContainedElementCount = InputData->ContainedElementCount;
+
+ if (ContainedElementCount > 1)
+ {
+ ExtendLength = (ContainedElementCount - 1) * sizeof (CONTAINED_ELEMENT);
+ }
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1
+ + ManuStrLen + 1
+ + VerStrLen + 1
+ + SerialNumStrLen + 1
+ + AssertTagStrLen + 1
+ + ChaNumStrLen + 1 + 1);
+ if (NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE3));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1;
+
+ ChassisType = GetChassisType ();
+ if (ChassisType != 0)
+ {
+ SmbiosRecord->Type = ChassisType;
+ }
+
+ //ContainedElements
+ (VOID)CopyMem(SmbiosRecord + 1, &ContainedElements, ExtendLength);
+
+ //ChassisSkuNumber
+ *((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength) = 5;
+
+ OptionalStrStart = (CHAR8 *)((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1);
+ UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart);
+ UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1);
+ UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1);
+ UnicodeStrToAsciiStr(AssertTag, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1);
+ UnicodeStrToAsciiStr(ChassisSkuNumber, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1 + SerialNumStrLen +1 + AssertTagStrLen + 1);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type03 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+
+Exit:
+ if(Manufacturer != NULL)
+ {
+ FreePool(Manufacturer);
+ }
+
+ if(Version != NULL)
+ {
+ FreePool(Version);
+ }
+
+ if(SerialNumber != NULL)
+ {
+ FreePool(SerialNumber);
+ }
+
+ if(AssertTag != NULL)
+ {
+ FreePool(AssertTag);
+ }
+
+ if(ChassisSkuNumber != NULL)
+ {
+ FreePool(ChassisSkuNumber);
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni
new file mode 100644
index 0000000000..19968f22f3
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignation.uni
Binary files differ
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c
new file mode 100644
index 0000000000..f9b1f03abd
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationData.c
@@ -0,0 +1,162 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2016, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscSystemSlotDesignationData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type09 Data
+
+**/
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie0) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // SlotDesignation
+ SlotTypePciExpressX8, // SlotType
+ SlotDataBusWidth8X, // SlotDataBusWidth
+ SlotUsageOther, // SlotUsage
+ SlotLengthOther, // SlotLength
+ 0x0000, // SlotId
+ { // SlotCharacteristics1
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 0, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0 // ModemRingResumeSupported:1;
+ },
+ { // SlotCharacteristics2
+ 0, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 0, // SmbusSignalSupported :1;
+ 0 // Reserved :5;
+ },
+ 0x00, // SegmentGroupNum
+ 0x00, // BusNum
+ 0 // DevFuncNum
+};
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie1) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // SlotDesignation
+ SlotTypePciExpressX8, // SlotType
+ SlotDataBusWidth8X, // SlotDataBusWidth
+ SlotUsageAvailable, // SlotUsage
+ SlotLengthOther, // SlotLength
+ 0x0001, // SlotId
+ { // SlotCharacteristics1
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 0, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0 // ModemRingResumeSupported:1;
+ },
+ { // SlotCharacteristics2
+ 0, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 0, // SmbusSignalSupported :1;
+ 0 // Reserved :5;
+ },
+ 0x00, // SegmentGroupNum
+ 0x40, // BusNum
+ 0 // DevFuncNum
+};
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie2) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // SlotDesignation
+ SlotTypePciExpressX8, // SlotType
+ SlotDataBusWidth8X, // SlotDataBusWidth
+ SlotUsageOther, // SlotUsage
+ SlotLengthOther, // SlotLength
+ 0x0002, // SlotId
+ { // SlotCharacteristics1
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 0, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0 // ModemRingResumeSupported:1;
+ },
+ { // SlotCharacteristics2
+ 0, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 0, // SmbusSignalSupported :1;
+ 0 // Reserved :5;
+ },
+ 0x00, // SegmentGroupNum
+ 0x80, // BusNum
+ 0 // DevFuncNum
+};
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE9, MiscSystemSlotDesignationPcie3) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 1, // SlotDesignation
+ SlotTypePciExpressX4, // SlotType
+ SlotDataBusWidth4X, // SlotDataBusWidth
+ SlotUsageOther, // SlotUsage
+ SlotLengthOther, // SlotLength
+ 0x0003, // SlotId
+ { // SlotCharacteristics1
+ 0, // CharacteristicsUnknown :1;
+ 0, // Provides50Volts :1;
+ 0, // Provides33Volts :1;
+ 0, // SharedSlot :1;
+ 0, // PcCard16Supported :1;
+ 0, // CardBusSupported :1;
+ 0, // ZoomVideoSupported :1;
+ 0 // ModemRingResumeSupported:1;
+ },
+ { // SlotCharacteristics2
+ 0, // PmeSignalSupported :1;
+ 0, // HotPlugDevicesSupported :1;
+ 0, // SmbusSignalSupported :1;
+ 0 // Reserved :5;
+ },
+ 0x00, // SegmentGroupNum
+ 0xC0, // BusNum
+ 0 // DevFuncNum
+};
+
+/* eof - MiscSystemSlotsData.c */
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c
new file mode 100644
index 0000000000..bc33639ac5
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type09/MiscSystemSlotDesignationFunction.c
@@ -0,0 +1,201 @@
+/** @file
+ BIOS system slot designator information boot time changes.
+ SMBIOS type 9.
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016, Hisilicon Limited. All rights reserved.<BR>
+ Copyright (c) 2016, Linaro Limited. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SmbiosMisc.h"
+
+#include <Library/SerdesLib.h>
+
+extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie0Data;
+extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie1Data;
+extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie2Data;
+extern SMBIOS_TABLE_TYPE9 MiscSystemSlotDesignationPcie3Data;
+
+VOID
+UpdateSlotDesignation (
+ IN SMBIOS_TABLE_TYPE9 *InputData
+ )
+{
+ STRING_REF TokenToUpdate;
+ CHAR16 *SlotDesignation;
+ UINTN DesignationStrLen;
+
+ SlotDesignation = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+ if (NULL == SlotDesignation)
+ {
+ return;
+ }
+
+ if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie0Data)
+ {
+ UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE0");
+ }
+ else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie1Data)
+ {
+ UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE1");
+ }
+ else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie2Data)
+ {
+ UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE2");
+ }
+ else if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie3Data)
+ {
+ UnicodeSPrint(SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE3");
+ }
+
+ DesignationStrLen = StrLen (SlotDesignation);
+
+ if (DesignationStrLen > 0 )
+ {
+ TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_DESIGNATION);
+ HiiSetString (mHiiHandle, TokenToUpdate, SlotDesignation, NULL);
+ }
+
+ FreePool (SlotDesignation);
+}
+
+VOID
+UpdateSlotUsage(
+ IN OUT SMBIOS_TABLE_TYPE9 *InputData
+ )
+{
+ EFI_STATUS Status;
+ SERDES_PARAM SerdesParamA;
+ SERDES_PARAM SerdesParamB;
+
+ Status = OemGetSerdesParam (&SerdesParamA, &SerdesParamB, 0);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] OemGetSerdesParam failed %r\n", __FUNCTION__, __LINE__, Status));
+ return;
+ }
+
+ //
+ // PCIE0
+ //
+ if (((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie0Data)
+ && SerdesParamA.Hilink1Mode == EmHilink1Pcie0X8) {
+ InputData->CurrentUsage = SlotUsageAvailable;
+ }
+
+ //
+ // PCIE1
+ //
+ if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie1Data)
+ {
+ if (SerdesParamA.Hilink0Mode == EmHilink0Pcie1X4Pcie2X4) {
+ InputData->SlotDataBusWidth = SlotDataBusWidth4X;
+ }
+ }
+
+ //
+ // PCIE2
+ //
+ if ((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie2Data)
+ {
+ if (SerdesParamA.Hilink0Mode == EmHilink0Pcie1X4Pcie2X4) {
+ InputData->SlotDataBusWidth = SlotDataBusWidth4X;
+ InputData->CurrentUsage = SlotUsageAvailable;
+ } else if (SerdesParamA.Hilink2Mode == EmHilink2Pcie2X8) {
+ InputData->CurrentUsage = SlotUsageAvailable;
+ }
+ }
+
+ //
+ // PCIE3
+ //
+ if (((UINTN)InputData == (UINTN)&MiscSystemSlotDesignationPcie3Data)
+ && SerdesParamA.Hilink5Mode == EmHilink5Pcie3X4) {
+ InputData->CurrentUsage = SlotUsageAvailable;
+ }
+}
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscSystemSlotDesignator structure (Type 9).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscSystemSlotDesignation)
+{
+ CHAR8 *OptionalStrStart;
+ UINTN SlotDesignationStrLen;
+ EFI_STATUS Status;
+ EFI_STRING SlotDesignation;
+ STRING_REF TokenToGet;
+ SMBIOS_TABLE_TYPE9 *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE9 *InputData = NULL;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE9 *)RecordData;
+
+ UpdateSlotUsage (InputData);
+
+ UpdateSlotDesignation (InputData);
+
+ TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_DESIGNATION);
+ SlotDesignation = HiiGetPackageString(&gEfiCallerIdGuid, TokenToGet, NULL);
+ SlotDesignationStrLen = StrLen(SlotDesignation);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1);
+ if(NULL == SmbiosRecord)
+ {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE9));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9);
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type09 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+
+Exit:
+ if(SlotDesignation != NULL)
+ {
+ FreePool(SlotDesignation);
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
new file mode 100644
index 0000000000..c9873ad890
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
@@ -0,0 +1,49 @@
+// *++
+//
+// Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+// Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+// --*/
+
+/=#
+
+/=#
+//
+// Language String (Long Format)
+//
+#string STR_MISC_BIOS_LANGUAGES_ENG_LONG #language en-US "en|US|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_FRA_LONG #language en-US "fr|CA|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_CHN_LONG #language en-US "zh|TW|unicode"
+#string STR_MISC_BIOS_LANGUAGES_JPN_LONG #language en-US "ja|JP|unicode"
+#string STR_MISC_BIOS_LANGUAGES_ITA_LONG #language en-US "it|IT|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_SPA_LONG #language en-US "es|ES|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_GER_LONG #language en-US "de|DE|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_POR_LONG #language en-US "pt|PT|iso8859-1"
+
+
+//
+// Language String (Abbreviated Format)
+//
+#string STR_MISC_BIOS_LANGUAGES_ENG_ABBREVIATE #language en-US "enUS"
+#string STR_MISC_BIOS_LANGUAGES_FRA_ABBREVIATE #language en-US "frCA"
+#string STR_MISC_BIOS_LANGUAGES_CHN_ABBREVIATE #language en-US "zhTW"
+#string STR_MISC_BIOS_LANGUAGES_JPN_ABBREVIATE #language en-US "jaJP"
+#string STR_MISC_BIOS_LANGUAGES_ITA_ABBREVIATE #language en-US "itIT"
+#string STR_MISC_BIOS_LANGUAGES_SPA_ABBREVIATE #language en-US "esES"
+#string STR_MISC_BIOS_LANGUAGES_GER_ABBREVIATE #language en-US "deDE"
+#string STR_MISC_BIOS_LANGUAGES_POR_ABBREVIATE #language en-US "ptPT"
+
+#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_ABBREVIATE #language en-US "zhCN"
+#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_LONG #language en-US "zh|CN|unicode"
+
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
new file mode 100644
index 0000000000..60f616085e
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
@@ -0,0 +1,46 @@
+/**@file
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscNumberOfInstallableLanguagesData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type13 Data
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE13, MiscNumberOfInstallableLanguages) =
+{
+ { // Hdr
+ EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ 0, // InstallableLanguages
+ 0, // Flags
+ {
+ 0 // Reserved[15]
+ },
+ 1 // CurrentLanguage
+};
+
+/* eof - MiscNumberOfInstallableLanguagesData.c */
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
new file mode 100644
index 0000000000..1f8f3eaf58
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
@@ -0,0 +1,163 @@
+/** @file
+
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+/**
+ Get next language from language code list (with separator ';').
+
+ @param LangCode Input: point to first language in the list. On
+ Otput: point to next language in the list, or
+ NULL if no more language in the list.
+ @param Lang The first language in the list.
+
+**/
+VOID
+EFIAPI
+GetNextLanguage (
+ IN OUT CHAR8 **LangCode,
+ OUT CHAR8 *Lang
+ )
+{
+ UINTN Index;
+ CHAR8 *StringPtr;
+
+ if(NULL == LangCode || NULL == *LangCode || NULL == Lang) {
+ return;
+ }
+
+ Index = 0;
+ StringPtr = *LangCode;
+ while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
+ Index++;
+ }
+
+ (VOID)CopyMem(Lang, StringPtr, Index);
+ Lang[Index] = 0;
+
+ if (StringPtr[Index] == ';') {
+ Index++;
+ }
+ *LangCode = StringPtr + Index;
+}
+
+/**
+ This function returns the number of supported languages on HiiHandle.
+
+ @param HiiHandle The HII package list handle.
+
+ @retval The number of supported languages.
+
+**/
+UINT16
+EFIAPI
+GetSupportedLanguageNumber (
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR8 *Lang;
+ CHAR8 *Languages;
+ CHAR8 *LanguageString;
+ UINT16 LangNumber;
+
+ Languages = HiiGetSupportedLanguages (HiiHandle);
+ if (Languages == NULL) {
+ return 0;
+ }
+
+ LangNumber = 0;
+ Lang = AllocatePool (AsciiStrSize (Languages));
+ if (Lang != NULL) {
+ LanguageString = Languages;
+ while (*LanguageString != 0) {
+ GetNextLanguage (&LanguageString, Lang);
+ LangNumber++;
+ }
+ FreePool (Lang);
+ }
+ FreePool (Languages);
+ return LangNumber;
+}
+
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscNumberOfInstallableLanguages (Type 13).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscNumberOfInstallableLanguages)
+{
+ UINTN LangStrLen;
+ CHAR8 CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1];
+ CHAR8 *OptionalStrStart;
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE13 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE13 *InputData = NULL;;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE13 *)RecordData;
+
+ InputData->InstallableLanguages = GetSupportedLanguageNumber (mHiiHandle);
+
+ //
+ // Try to check if current langcode matches with the langcodes in installed languages
+ //
+ ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1);
+ (VOID)AsciiStrCpyS(CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1, "en|US|iso8859-1");
+ LangStrLen = AsciiStrLen(CurrentLang);
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
+ if(NULL == SmbiosRecord) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE13));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13);
+
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+ (VOID)AsciiStrCpyS(OptionalStrStart, SMBIOS_STRING_MAX_LENGTH - 1, CurrentLang);
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData((UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type13 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
new file mode 100644
index 0000000000..9f04694548
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
@@ -0,0 +1,48 @@
+/**@file
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscBootInformationData.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to the DataHub.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE32, MiscBootInformation) = {
+ { // Hdr
+ EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, // Type,
+ 0, // Length,
+ 0 // Handle
+ },
+ { // Reserved[6]
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ BootInformationStatusNoError // BootInformationStatus
+};
+
+/* eof - MiscBootInformationData.c */
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
new file mode 100644
index 0000000000..7840445eb8
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
@@ -0,0 +1,74 @@
+/** @file
+ boot information boot time changes.
+ SMBIOS type 32.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+/**
+ This function makes boot time changes to the contents of the
+ MiscBootInformation (Type 32).
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+
+MISC_SMBIOS_TABLE_FUNCTION(MiscBootInformation)
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE32 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE32 *InputData;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE32 *)RecordData;
+
+ //
+ // Two zeros following the last string.
+ //
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE32) + 1 + 1);
+ if(NULL == SmbiosRecord) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE32));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE32);
+
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData( (UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type32 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c
new file mode 100644
index 0000000000..2dc99f1f9c
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationData.c
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscIpmiDeviceInformationData.c
+
+Abstract:
+
+ This file provide OEM to define Smbios Type38 Data
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+
+#include "SmbiosMisc.h"
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE38, MiscIpmiDeviceInformation) =
+{
+ { // Header
+ EFI_SMBIOS_TYPE_IPMI_DEVICE_INFORMATION, // Type;
+ 0, // Length;
+ 0 // Handle;
+ },
+ IPMIDeviceInfoInterfaceTypeUnknown, // InterfaceType
+ 0x00, // Ipmi Specification Revision
+ 0, // I2CSlaveAddress
+ 0xFF, // NvStorageDeviceAddress
+ 0x88, // BaseAddress
+ 0, // BaseAddressModifier/InterruptInfo
+ 0 // InterruptNumber
+};
+
diff --git a/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c
new file mode 100644
index 0000000000..f198237e4d
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/Smbios/SmbiosMiscDxe/Type38/MiscIpmiDeviceInformationFunction.c
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MiscIpmiDeviceInformationFunction.c
+
+Abstract:
+
+ This driver parses the mMiscSubclassDataTable structure and reports
+ any generated data to smbios.
+
+Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+**/
+/* Modify list
+DATA AUTHOR REASON
+*/
+
+#include "SmbiosMisc.h"
+
+#include <Protocol/IpmiInterfaceProtocol.h>
+
+/**
+ This function makes the attributes of IPMI to the contents of the
+ MiscChassisManufacturer structure.
+
+ @param RecordData Pointer to copy of RecordData from the Data Table.
+
+ @retval EFI_SUCCESS All parameters were valid.
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscIpmiDeviceInformation)
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ SMBIOS_TABLE_TYPE38 *SmbiosRecord;
+ SMBIOS_TABLE_TYPE38 *InputData = NULL;
+
+ IPMI_INTERFACE_PROTOCOL *Ipmi;
+
+ //
+ // First check for invalid parameters.
+ //
+ if (RecordData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InputData = (SMBIOS_TABLE_TYPE38*)RecordData;
+
+ SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE38) + 1 + 1);
+ if(NULL == SmbiosRecord) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (VOID)CopyMem(SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE38));
+
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE38);
+
+ Status = gBS->LocateProtocol (&gIpmiInterfaceProtocolGuid, NULL, (VOID **)&Ipmi);
+ if (!EFI_ERROR (Status)) {
+ SmbiosRecord->InterfaceType = Ipmi->GetIpmiInterfaceType (Ipmi);
+ SmbiosRecord->BaseAddress = (UINT64)Ipmi->GetIpmiBaseAddress (Ipmi) | Ipmi->GetIpmiBaseAddressType (Ipmi);
+ SmbiosRecord->IPMISpecificationRevision = Ipmi->GetIpmiVersion (Ipmi);
+ }
+ //
+ // Now we have got the full smbios record, call smbios protocol to add this record.
+ //
+ Status = LogSmbiosData((UINT8*)SmbiosRecord, &SmbiosHandle);
+ if(EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type38 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
+ }
+
+ FreePool(SmbiosRecord);
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c
new file mode 100644
index 0000000000..699a820108
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.c
@@ -0,0 +1,158 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+
+#include <Uefi.h>
+#include <Pi/PiDxeCis.h>
+#include <Library/DebugLib.h>
+#include <libfdt.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Guid/Fdt.h>
+#include <Protocol/HisiBoardNicProtocol.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/FdtUpdateLib.h>
+
+STATIC
+EFI_STATUS
+InstallFdtIntoConfigurationTable (
+ IN VOID* FdtBlob,
+ IN UINTN FdtSize
+ )
+{
+ EFI_STATUS Status;
+
+ // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on
+ // production device and this ASSERT() becomes not valid.
+ if(!(fdt_check_header (FdtBlob) == 0))
+ {
+ DEBUG ((EFI_D_ERROR,"can not find FdtBlob \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Ensure the Size of the Device Tree is smaller than the size of the read file
+ if(!((UINTN)fdt_totalsize (FdtBlob) <= FdtSize))
+ {
+ DEBUG ((EFI_D_ERROR,"FdtBlob <= FdtSize \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Install the FDT into the Configuration Table
+ Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtBlob);
+
+ return Status;
+}
+
+EFI_STATUS
+SetNvramSpace (VOID)
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0};
+
+ if (PcdGet64(PcdReservedNvramSize) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gDS->GetMemorySpaceDescriptor(PcdGet64(PcdReservedNvramBase),&desp);
+ if(EFI_ERROR(Status)){
+ DEBUG ((EFI_D_ERROR,"get memory space error:--------- \n"));
+ return Status;
+ }
+ desp.Attributes |= EFI_MEMORY_RUNTIME | EFI_MEMORY_WB;
+ Status = gDS->SetMemorySpaceAttributes(PcdGet64(PcdReservedNvramBase),PcdGet64(PcdReservedNvramSize), desp.Attributes);
+ if(EFI_ERROR(Status)){
+ DEBUG ((EFI_D_ERROR,"set memory space error:--------- \n"));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI UpdateFdt (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ INTN Error;
+ VOID* Fdt;
+ UINT32 Size;
+ UINTN NewFdtBlobSize;
+ UINTN NewFdtBlobBase;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 Index = 0;
+ UINTN FDTConfigTable;
+
+ (VOID) SetNvramSpace ();
+
+ Fdt = (VOID*)(PcdGet64(FdtFileAddress));
+
+
+ Error = fdt_check_header ((VOID*)(PcdGet64(FdtFileAddress)));
+ DEBUG ((EFI_D_ERROR,"fdtfileaddress:--------- 0x%lx\n",PcdGet64(FdtFileAddress)));
+ if (Error != 0)
+ {
+ DEBUG ((EFI_D_ERROR,"ERROR: Device Tree header not valid (%a)\n", fdt_strerror(Error)));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Size = (UINTN)fdt_totalsize ((VOID*)(PcdGet64(FdtFileAddress)));
+ NewFdtBlobSize = Size + ADD_FILE_LENGTH;
+
+ Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
+ if (EFI_ERROR (Status))
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (VOID) CopyMem((VOID*)NewFdtBlobBase, Fdt, Size);
+
+ Status = EFIFdtUpdate(NewFdtBlobBase);
+ if (EFI_ERROR (Status))
+ {
+ DEBUG((EFI_D_ERROR, "%a(%d):EFIFdtUpdate Fail!\n", __FUNCTION__,__LINE__));
+ goto EXIT;
+ }
+
+
+ Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)NewFdtBlobBase, NewFdtBlobSize);
+ DEBUG ((EFI_D_ERROR, "NewFdtBlobBase: 0x%lx NewFdtBlobSize:0x%lx\n",NewFdtBlobBase,NewFdtBlobSize));
+ if (EFI_ERROR (Status))
+ {
+ DEBUG ((EFI_D_ERROR, "installfdtconfiguration table fail():\n"));
+ goto EXIT;
+ }
+
+
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index ++)
+ {
+ if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid)))
+ {
+ FDTConfigTable = (UINTN)gST->ConfigurationTable[Index].VendorTable;
+ DEBUG ((EFI_D_ERROR, "FDTConfigTable Address: 0x%lx\n",FDTConfigTable));
+ break;
+ }
+ }
+
+ return Status;
+
+ EXIT:
+
+ gBS->FreePages(NewFdtBlobBase,EFI_SIZE_TO_PAGES(NewFdtBlobSize));
+
+ return Status;
+
+}
diff --git a/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf
new file mode 100644
index 0000000000..ccdcae7acf
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/UpdateFdtDxe/UpdateFdtDxe.inf
@@ -0,0 +1,62 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UpdateFdtDxe
+ FILE_GUID = E29977F9-20A4-4551-B0EC-BCE246592E76
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = UpdateFdt
+
+[Sources.common]
+ UpdateFdtDxe.c
+
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ OpenPlatformPkg/Chips/Hisilicon/HisiPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ DebugLib
+ BaseLib
+ FdtLib
+ PcdLib
+ FdtUpdateLib
+ DxeServicesTableLib
+
+[Guids]
+ gFdtTableGuid
+[Protocols]
+
+ gHisiBoardNicProtocolGuid
+
+[Pcd]
+
+ gHisiTokenSpaceGuid.FdtFileAddress
+ gHisiTokenSpaceGuid.PcdReservedNvramSize
+ gHisiTokenSpaceGuid.PcdReservedNvramBase
+
+
+[Depex]
+ gEfiGenericMemTestProtocolGuid
diff --git a/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c
new file mode 100644
index 0000000000..40e9137d78
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.c
@@ -0,0 +1,108 @@
+/** @file
+*
+* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2016, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+
+#include <Guid/VersionInfoHobGuid.h>
+
+struct MonthDescription {
+ CONST CHAR8* MonthStr;
+ UINT32 MonthInt;
+} gMonthDescription[] = {
+ { "Jan", 1 },
+ { "Feb", 2 },
+ { "Mar", 3 },
+ { "Apr", 4 },
+ { "May", 5 },
+ { "Jun", 6 },
+ { "Jul", 7 },
+ { "Aug", 8 },
+ { "Sep", 9 },
+ { "Oct", 10 },
+ { "Nov", 11 },
+ { "Dec", 12 },
+ { "???", 1 }, // Use 1 as default month
+};
+
+VOID GetReleaseTime (EFI_TIME *Time)
+{
+ CONST CHAR8 *ReleaseDate = __DATE__;
+ CONST CHAR8 *ReleaseTime = __TIME__;
+ UINTN i;
+
+ for(i=0;i<12;i++)
+ {
+ if(0 == AsciiStrnCmp(ReleaseDate, gMonthDescription[i].MonthStr, 3))
+ {
+ break;
+ }
+ }
+ Time->Month = gMonthDescription[i].MonthInt;
+ Time->Day = AsciiStrDecimalToUintn(ReleaseDate+4);
+ Time->Year = AsciiStrDecimalToUintn(ReleaseDate+7);
+ Time->Hour = AsciiStrDecimalToUintn(ReleaseTime);
+ Time->Minute = AsciiStrDecimalToUintn(ReleaseTime+3);
+ Time->Second = AsciiStrDecimalToUintn(ReleaseTime+6);
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+VersionInfoEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+ VERSION_INFO *VersionInfo;
+ EFI_TIME Time = {0};
+ CONST CHAR16 *ReleaseString =
+ (CHAR16 *) FixedPcdGetPtr (PcdFirmwareVersionString);
+
+ GetReleaseTime (&Time);
+
+ CharCount = AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "\n\rBoot firmware (version %s built at %t)\n\r\n\r",
+ ReleaseString,
+ &Time
+ );
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ VersionInfo = BuildGuidHob (&gVersionInfoHobGuid,
+ sizeof (VERSION_INFO) -
+ sizeof (VersionInfo->String) +
+ StrSize (ReleaseString));
+ if (VersionInfo == NULL) {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%d] Build HOB failed!\n", __FILE__, __LINE__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (&VersionInfo->BuildTime, &Time, sizeof (EFI_TIME));
+ CopyMem (VersionInfo->String, ReleaseString, StrSize (ReleaseString));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf
new file mode 100644
index 0000000000..ac39411a77
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/VersionInfoPeim/VersionInfoPeim.inf
@@ -0,0 +1,53 @@
+#/** @file
+#
+# Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VersionInfoPeim
+ FILE_GUID = F414EE11-EEE3-4edc-8C12-0E80E446A849
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = VersionInfoEntry
+
+[Sources.common]
+ VersionInfoPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PcdLib
+ DebugLib
+ HobLib
+ BaseLib
+ BaseMemoryLib
+ PrintLib
+ SerialPortLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+
+[Guids]
+ gVersionInfoHobGuid
+
+[Depex]
+ TRUE
+
+[BuildOptions]
+
diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c
new file mode 100644
index 0000000000..0cb1e8049a
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.c
@@ -0,0 +1,682 @@
+/** @file
+*
+* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2016, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "VirtualEhciPciIo.h"
+#include <Protocol/PciRootBridgeIo.h>
+
+UINT32 mUsbMemBase;
+UINTN mSegmentNumber = 0;
+// Use 0xFF for the virtual PCI devices
+UINTN mBusNumber = 0xFF;
+UINTN mDeviceNumber = 0;
+UINTN mFunctionNumber = 0;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN NumberOfBytes;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+ BOOLEAN DoubleBuffer;
+} MEM_MAP_INFO_INSTANCE;
+
+
+EFI_CPU_ARCH_PROTOCOL *gCpu;
+
+
+EHCI_PCI_CONFIG mEhciPciConfig = {
+ {
+ 0x00,//UINT16 VendorId;
+ 0x00,//UINT16 DeviceId;
+ 0x00,//UINT16 Command;
+ 0x0010,//UINT16 Status;
+ 0x00,//UINT8 RevisionID;
+ {
+ PCI_IF_EHCI,//UINT8 ClassCode[3];
+ PCI_CLASS_SERIAL_USB,
+ PCI_CLASS_SERIAL
+ },
+ 0x00,//UINT8 CacheLineSize;
+ 0x00,//UINT8 LatencyTimer;
+ 0x00,//UINT8 HeaderType;
+ 0x00//UINT8 BIST;
+ },
+ {
+ {
+ 0x00,//UINT32 Bar[6];
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ },
+ 0x00,//UINT32 CISPtr;
+ 0x00,//UINT16 SubsystemVendorID;
+ 0x00,//UINT16 SubsystemID;
+ 0x00,//UINT32 ExpansionRomBar;
+ 0x40,//UINT8 CapabilityPtr;
+ {
+ 0x00,//UINT8 Reserved1[3];
+ 0x00,
+ 0x00
+ },
+ 0x00,//UINT32 Reserved2;
+ 0x00,//UINT8 InterruptLine;
+ 0x00,//UINT8 InterruptPin;
+ 0x00,//UINT8 MinGnt;
+ 0x00//UINT8 MaxLat;
+ },
+ 0x0A,// UINT8 CapabilityID offset 0x40
+ 0x00,// UINT8 NextItemPtr
+ 0x2000 //UINT16 DebugPort
+};
+
+
+
+EFI_STATUS
+EhciPciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 i;
+
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BarIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Width = Width & 0x03;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (i = 0; i < Count; i++){
+ *((UINT8 *)Buffer + i)= MmioRead8(mUsbMemBase + Offset + i);
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (i = 0; i < Count; i++){
+ *((UINT16 *)Buffer + i)= MmioRead16(mUsbMemBase + Offset + i * 2);
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (i = 0; i < Count; i++){
+ *((UINT32 *)Buffer + i)= MmioRead32(mUsbMemBase + Offset + i * 4);
+ }
+ break;
+ case EfiPciWidthUint64:
+ for (i = 0; i < Count; i++){
+ *((UINT64 *)Buffer + i)= MmioRead64(mUsbMemBase + Offset + i * 8);
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 i;
+
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Width = Width & 0x03;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (i = 0; i < Count; i++){
+ MmioWrite8(mUsbMemBase + Offset + i, *((UINT8 *)Buffer + i));
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (i = 0; i < Count; i++){
+ MmioWrite16(mUsbMemBase + Offset + i * 2, *((UINT16 *)Buffer + i));
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (i = 0; i < Count; i++){
+ MmioWrite32(mUsbMemBase + Offset + i * 4, *((UINT32 *)Buffer + i));
+ }
+ break;
+ case EfiPciWidthUint64:
+ for (i = 0; i < Count; i++){
+ MmioWrite64(mUsbMemBase + Offset + i * 8, *((UINT64 *)Buffer + i));
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EhciPciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoPciRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 i;
+ UINT8 *DataPtr;
+
+ Width = Width & 0x03;
+
+ if (Offset < sizeof (EHCI_PCI_CONFIG) / sizeof (UINT8)){
+
+ DataPtr = (UINT8 *)(&mEhciPciConfig) + Offset;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (i = 0; i < Count; i++){
+ *((UINT8 *)Buffer + i)= *(DataPtr + i);
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (i = 0; i < Count; i++){
+ *((UINT16 *)Buffer + i)= *((UINT16 *)DataPtr + i);
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (i = 0; i < Count; i++){
+ *(UINT32 *)(Buffer + i)= *((UINT32 *)DataPtr + i);
+ }
+ break;
+ case EfiPciWidthUint64:
+ for (i = 0; i < Count; i++){
+ *(UINT64 *)(Buffer + i)= *((UINT64 *)DataPtr + i);
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else {
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *(UINT8 *)Buffer = 0xFF;
+ break;
+ case EfiPciWidthUint16:
+ *(UINT16 *)Buffer = 0xFFFF;
+ break;
+ case EfiPciWidthUint32:
+ *(UINT32 *)Buffer = 0xFFFFFFFF;
+ break;
+ case EfiPciWidthUint64:
+ *(UINT64 *)Buffer = 0xFFFFFFFFFFFFFFFF;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoPciWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ MEM_MAP_INFO_INSTANCE *Map;
+ VOID *Buffer;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DeviceAddress = ConvertToPhysicalAddress (HostAddress);
+
+ // Remember range so we can flush on the other side
+ Map = AllocatePool (sizeof (MEM_MAP_INFO_INSTANCE));
+ if (Map == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Mapping = Map;
+
+ if ((((UINTN)HostAddress & (EFI_PAGE_SIZE - 1)) != 0) ||
+ ((*NumberOfBytes % EFI_PAGE_SIZE) != 0)) {
+
+ // Get the cacheability of the region
+ Status = gDS->GetMemorySpaceDescriptor (*DeviceAddress, &GcdDescriptor);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // If the mapped buffer is not an uncached buffer
+ if ( (GcdDescriptor.Attributes != EFI_MEMORY_WC) &&
+ (GcdDescriptor.Attributes != EFI_MEMORY_UC) )
+ {
+ //
+ // If the buffer does not fill entire cache lines we must double buffer into
+ // uncached memory. Device (PCI) address becomes uncached page.
+ //
+ Map->DoubleBuffer = TRUE;
+ Buffer = UncachedAllocatePages(EFI_SIZE_TO_PAGES (*NumberOfBytes));
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Buffer, HostAddress, *NumberOfBytes);
+ *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
+ } else {
+ Map->DoubleBuffer = FALSE;
+ }
+ } else {
+ Map->DoubleBuffer = FALSE;
+
+ // Flush the Data Cache (should not have any effect if the memory region is uncached)
+ gCpu->FlushDataCache (gCpu, *DeviceAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate);
+
+ Status = gDS->SetMemorySpaceAttributes (*DeviceAddress & ~(BASE_4KB - 1), ALIGN_VALUE (*NumberOfBytes, BASE_4KB), EFI_MEMORY_WC);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] SetMemorySpaceAttributes Fail. %r\n", __FUNCTION__, __LINE__, Status));
+ }
+ }
+
+ Map->HostAddress = (UINTN)HostAddress;
+ Map->DeviceAddress = *DeviceAddress;
+ Map->NumberOfBytes = *NumberOfBytes;
+ Map->Operation = Operation;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ MEM_MAP_INFO_INSTANCE *Map;
+
+ if (Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Map = (MEM_MAP_INFO_INSTANCE *)Mapping;
+
+ if (Map->DoubleBuffer) {
+ if ((Map->Operation == EfiPciIoOperationBusMasterWrite) || (Map->Operation == EfiPciIoOperationBusMasterCommonBuffer)) {
+ CopyMem ((VOID *)(UINTN)Map->HostAddress, (VOID *)(UINTN)Map->DeviceAddress, Map->NumberOfBytes);
+ }
+
+ if((VOID *)(UINTN)Map->DeviceAddress != NULL) {
+ UncachedFreePages ((VOID *)(UINTN)Map->DeviceAddress, EFI_SIZE_TO_PAGES (Map->NumberOfBytes));
+ }
+
+
+ } else {
+ if (Map->Operation == EfiPciIoOperationBusMasterWrite) {
+ //
+ // Make sure we read buffer from uncached memory and not the cache
+ //
+ gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate);
+ }
+ }
+
+ FreePool (Map);
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EhciPciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ UINT32 HcCapParams;
+
+ if (Attributes &
+ (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MemoryType == EfiBootServicesData) {
+ HcCapParams = MmioRead32(mUsbMemBase + EHC_HCCPARAMS_OFFSET);
+ if ((BOOLEAN)(((HcCapParams) & (HCCP_64BIT)) == (HCCP_64BIT))){
+ *HostAddress = UncachedAllocatePages(Pages);
+ } else {
+ // TODO: We need support allocating UC memory below 4GB strictly
+ *HostAddress = UncachedAllocatePages(Pages);
+ }
+
+ }else{
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EhciPciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ UncachedFreePages (HostAddress, Pages);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *SegmentNumber,
+ OUT UINTN *BusNumber,
+ OUT UINTN *DeviceNumber,
+ OUT UINTN *FunctionNumber
+ )
+{
+
+ *SegmentNumber = mSegmentNumber;
+ *BusNumber = mBusNumber;
+ *DeviceNumber = mDeviceNumber;
+ *FunctionNumber = mFunctionNumber;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EhciPciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+{
+ if (Result != NULL) {
+ *Result = 0;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EhciPciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EhciPciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+//
+// Pci Io Protocol Interface
+//
+EFI_PCI_IO_PROTOCOL mEhciPciIoInterface = {
+ EhciPciIoPollMem,
+ EhciPciIoPollIo,
+ {
+ EhciPciIoMemRead,
+ EhciPciIoMemWrite
+ },
+ {
+ EhciPciIoIoRead,
+ EhciPciIoIoWrite
+ },
+ {
+ EhciPciIoPciRead,
+ EhciPciIoPciWrite
+ },
+ EhciPciIoCopyMem,
+ EhciPciIoMap,
+ EhciPciIoUnmap,
+ EhciPciIoAllocateBuffer,
+ EhciPciIoFreeBuffer,
+ EhciPciIoFlush,
+ EhciPciIoGetLocation,
+ EhciPciIoAttributes,
+ EhciPciIoGetBarAttributes,
+ EhciPciIoSetBarAttributes,
+ 0,
+ NULL
+};
+
+
+EFI_STATUS
+EFIAPI
+EhciVirtualPciIoInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_DEV_PATH EndNode;
+ EFI_DEV_PATH Node;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
+
+ mUsbMemBase = PlatformGetEhciBase ();
+
+ DEBUG ((EFI_D_ERROR, "mUsbMemBase: 0x%x\n", mUsbMemBase));
+
+ // Get the Cpu protocol for later use
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
+
+ //
+ // Install the pciio protocol, device path protocol
+ //
+ Handle = NULL;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiPciIoProtocolGuid,
+ &mEhciPciIoInterface,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ (void)ZeroMem (&Node, sizeof (Node));
+ Node.DevPath.Type = HARDWARE_DEVICE_PATH;
+ Node.DevPath.SubType = HW_PCI_DP;
+ (void)SetDevicePathNodeLength (&Node.DevPath, sizeof (PCI_DEVICE_PATH));
+ // Make USB controller device path different from built-in SATA controller
+ Node.Pci.Function = 1;
+ Node.Pci.Device = 0;
+
+ SetDevicePathEndNode (&EndNode.DevPath);
+
+ DevicePath = AppendDevicePathNode (&EndNode.DevPath, &Node.DevPath);
+
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ DevicePath
+ );
+ if(EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] InstallProtocolInterface fail. %r\n", __FUNCTION__, __LINE__, Status));
+ }
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h
new file mode 100644
index 0000000000..ae7a934a11
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.h
@@ -0,0 +1,82 @@
+/** @file
+*
+* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2016, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _EHCI_PCIIO_H_
+#define _EHCI_PCIIO_H_
+
+#include <Uefi.h>
+#include <PiDxe.h>
+
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/Cpu.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/ArmLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/CacheMaintenanceLib.h>
+
+#include <Library/ReportStatusCodeLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <Library/PlatformSysCtrlLib.h>
+
+#define PCI_CLASS_SERIAL 0x0C
+#define PCI_CLASS_SERIAL_FIREWIRE 0x00
+#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01
+#define PCI_CLASS_SERIAL_SSA 0x02
+#define PCI_CLASS_SERIAL_USB 0x03
+#define PCI_IF_EHCI 0x20
+#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04
+#define PCI_CLASS_SERIAL_SMB 0x05
+
+//
+// Capability register offset
+//
+#define EHC_CAPLENGTH_OFFSET 0 // Capability register length offset
+#define EHC_HCSPARAMS_OFFSET 0x04 // Structural Parameters 04-07h
+#define EHC_HCCPARAMS_OFFSET 0x08 // Capability parameters offset
+
+//
+// Capability register bit definition
+//
+#define HCSP_NPORTS 0x0F // Number of root hub port
+#define HCSP_PPC 0x10 // Port Power Control
+#define HCCP_64BIT 0x01 // 64-bit addressing capability
+
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_DEVICE_HEADER_TYPE_REGION Device;
+ UINT8 CapabilityID;
+ UINT8 NextItemPtr;
+ UINT16 DebugPort;
+} EHCI_PCI_CONFIG;
+
+
+#endif // _EHCI_PCIIO_H_
diff --git a/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf
new file mode 100644
index 0000000000..4a5f5c30bc
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/VirtualEhciPciIo/VirtualEhciPciIo.inf
@@ -0,0 +1,60 @@
+#/** @file
+#
+# Copyright (c) 2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VirtualEhciPciIo
+ FILE_GUID = CCC39A9C-33EC-4e5a-924B-2C5CD4CEF6A4
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = EhciVirtualPciIoInitialize
+
+
+[Sources]
+ VirtualEhciPciIo.h
+ VirtualEhciPciIo.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[FeaturePcd]
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ IoLib
+ ReportStatusCodeLib
+ UncachedMemoryAllocationLib
+ ArmLib
+ DxeServicesTableLib
+ CacheMaintenanceLib
+ PlatformSysCtrlLib
+
+[Guids]
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START