summaryrefslogtreecommitdiff
path: root/Silicon/Hisilicon/Library
diff options
context:
space:
mode:
authorLeif Lindholm <leif.lindholm@linaro.org>2017-08-03 12:24:30 +0100
committerLeif Lindholm <leif.lindholm@linaro.org>2017-08-03 12:24:30 +0100
commit600081b52debde8d06585fdaf09fac16d323670f (patch)
treefef3287095bb56eba411c0b31c525283978b71fb /Silicon/Hisilicon/Library
parentf4d38e50c0f24eb78eb003a94f583025621c63db (diff)
downloadedk2-platforms-600081b52debde8d06585fdaf09fac16d323670f.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.0 Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Diffstat (limited to 'Silicon/Hisilicon/Library')
-rw-r--r--Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S61
-rw-r--r--Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c107
-rw-r--r--Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf69
-rw-r--r--Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c97
-rw-r--r--Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf56
-rw-r--r--Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c53
-rw-r--r--Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf47
-rw-r--r--Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c104
-rw-r--r--Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf51
-rw-r--r--Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h178
-rw-r--r--Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c433
-rw-r--r--Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf48
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c302
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h116
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf45
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c356
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h116
-rw-r--r--Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf52
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CHw.h269
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLib.c655
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLib.inf49
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c35
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h29
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c109
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf51
-rw-r--r--Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c963
-rw-r--r--Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h61
-rw-r--r--Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c118
-rw-r--r--Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h27
-rw-r--r--Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf84
-rw-r--r--Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c429
-rw-r--r--Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf47
32 files changed, 5217 insertions, 0 deletions
diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S
new file mode 100644
index 0000000000..3422df279c
--- /dev/null
+++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2011-2013, 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 the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+#include <Library/ArmLib.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+ ret
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+ MOV32 (w0, FixedPcdGet32(PcdArmPrimaryCore))
+ ret
+
+# IN None
+# OUT x0 = number of cores present in the system
+ASM_FUNC(ArmGetCpuCountPerCluster)
+ MOV32 (w0, FixedPcdGet32(PcdCoreCount))
+ ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+ MOV32 (w1, FixedPcdGet32(PcdArmPrimaryCoreMask))
+ and x0, x0, x1
+ MOV32 (w1, FixedPcdGet32(PcdArmPrimaryCore))
+ cmp w0, w1
+ cset x0, eq
+ ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_FUNC(ArmPlatformGetCorePosition)
+ and x1, x0, #ARM_CORE_MASK
+ and x0, x0, #ARM_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c
new file mode 100644
index 0000000000..07ab0d1dc2
--- /dev/null
+++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c
@@ -0,0 +1,107 @@
+/** @file
+*
+* Copyright (c) 2011-2013, 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 the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+UINTN
+ArmGetCpuCountPerCluster (
+ VOID
+ );
+
+extern EFI_STATUS MemInitEntry (VOID);
+
+/**
+ Return the current Boot Mode
+
+ This function returns the boot reason on the platform
+
+ @return Return the current Boot Mode of the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+ VOID
+ )
+{
+ return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+ Initialize controllers that must setup in the normal world
+
+ This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim
+ in the PEI phase.
+
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+/**
+ Initialize the system (or sometimes called permanent) memory
+
+ This memory is generally represented by the DRAM.
+
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+ VOID
+ )
+{
+ // Nothing to do here
+}
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+ OUT UINTN *CoreCount,
+ OUT ARM_CORE_INFO **ArmCoreTable
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+// Needs to be declared in the file. Otherwise gArmMpCoreInfoPpiGuid is undefined in the contect of PrePeiCore
+EFI_GUID mArmMpCoreInfoPpiGuid = ARM_MP_CORE_INFO_PPI_GUID;
+ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
+
+EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &mArmMpCoreInfoPpiGuid,
+ &mMpCoreInfoPpi
+ }
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ *PpiListSize = sizeof(gPlatformPpiTable);
+ *PpiList = gPlatformPpiTable;
+}
diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf
new file mode 100644
index 0000000000..f4dc68f762
--- /dev/null
+++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf
@@ -0,0 +1,69 @@
+#/* @file
+# Copyright (c) 2011-2014, 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 the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformLibPv660
+ FILE_GUID = 6887500D-32AD-41cd-855E-F8A5D5B0D4D2
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ ArmLib
+ MemoryAllocationLib
+ SerialPortLib
+
+[Sources.common]
+ ArmPlatformLib.c
+ ArmPlatformLibMem.c
+
+[Sources.AARCH64]
+ AArch64/Helper.S
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable
+ gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+ gHisiTokenSpaceGuid.PcdNORFlashBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gHisiTokenSpaceGuid.PcdSysControlBaseAddress
+ gHisiTokenSpaceGuid.PcdPeriSubctrlAddress
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase
+
diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c
new file mode 100644
index 0000000000..b7bc75dc74
--- /dev/null
+++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c
@@ -0,0 +1,97 @@
+/** @file
+*
+* Copyright (c) 2011-2014, 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 the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Library/OemSetVirtualMapDesc.h>
+
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 32
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+/**
+ Return the Virtual Memory Map of your platform
+
+ This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform.
+
+ @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to-
+ Virtual Memory mapping. This array must be ended by a zero-filled
+ entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+ IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+ )
+{
+ ARM_MEMORY_REGION_ATTRIBUTES CacheAttributes;
+ UINTN Index;
+ ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
+ EFI_PEI_HOB_POINTERS NextHob;
+
+ ASSERT (VirtualMemoryMap != NULL);
+
+ VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+ if (VirtualMemoryTable == NULL) {
+ return;
+ }
+
+ if (FeaturePcdGet(PcdCacheEnable) == TRUE) {
+ CacheAttributes = DDR_ATTRIBUTES_CACHED;
+ } else {
+ CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
+ }
+
+ Index = OemSetVirtualMapDesc(VirtualMemoryTable, CacheAttributes);
+
+ // Search for System Memory Hob that contains the EFI resource system memory
+ NextHob.Raw = GetHobList ();
+ while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL)
+ {
+ if (NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)
+ {
+ if (NextHob.ResourceDescriptor->PhysicalStart > BASE_4GB)
+ {
+ VirtualMemoryTable[++Index].PhysicalBase = NextHob.ResourceDescriptor->PhysicalStart;
+ VirtualMemoryTable[Index].VirtualBase = NextHob.ResourceDescriptor->PhysicalStart;
+ VirtualMemoryTable[Index].Length =NextHob.ResourceDescriptor->ResourceLength;
+ VirtualMemoryTable[Index].Attributes = CacheAttributes;
+ }
+ }
+
+ NextHob.Raw = GET_NEXT_HOB (NextHob);
+ }
+
+ // End of Table
+ VirtualMemoryTable[++Index].PhysicalBase = 0;
+ VirtualMemoryTable[Index].VirtualBase = 0;
+ VirtualMemoryTable[Index].Length = 0;
+ VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0;
+
+ ASSERT((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+ DEBUG((EFI_D_INFO, "[%a]:[%dL] discriptor count=%d\n", __FUNCTION__, __LINE__, Index+1));
+
+ *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf
new file mode 100644
index 0000000000..fa308bd066
--- /dev/null
+++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf
@@ -0,0 +1,56 @@
+#/* @file
+# Copyright (c) 2011-2012, 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 the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformLibPv660Sec
+ FILE_GUID = a79eed97-4b98-4974-9690-37b32d6a5b56
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ ArmLib
+ SerialPortLib
+
+[Sources.common]
+ ArmPlatformLib.c
+
+[Sources.AARCH64]
+ AArch64/Helper.S
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable
+ gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c
new file mode 100644
index 0000000000..72bb7f5305
--- /dev/null
+++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c
@@ -0,0 +1,53 @@
+/** @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/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/CpldIoLib.h>
+
+
+VOID WriteCpldReg(UINTN ulRegAddr, UINT8 ulValue)
+{
+ MmioWrite8 (ulRegAddr + PcdGet64(PcdCpldBaseAddress), ulValue);
+}
+
+
+UINT8 ReadCpldReg(UINTN ulRegAddr)
+{
+ return MmioRead8 (ulRegAddr + PcdGet64(PcdCpldBaseAddress));
+}
+
+
+VOID ReadCpldBytes(UINT16 Addr, UINT8 *Data, UINT8 Bytes)
+{
+ UINT8 i;
+
+ for(i = 0;i < Bytes; i++)
+ {
+ *(Data + i) = ReadCpldReg(Addr + i);
+ }
+}
+
+VOID WriteCpldBytes(UINT16 Addr, UINT8 *Data, UINT8 Bytes)
+{
+ UINT8 i;
+
+ for(i = 0; i < Bytes; i++)
+ {
+ WriteCpldReg(Addr + i, *(Data + i));
+ }
+}
diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf
new file mode 100644
index 0000000000..d3378a020b
--- /dev/null
+++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf
@@ -0,0 +1,47 @@
+#/** @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 = CpldIoLib
+ FILE_GUID = 4633665C-0029-464E-9788-58B8D49FF57E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpldIoLib
+
+[Sources.common]
+ CpldIoLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ BaseLib
+ ArmLib
+ TimerLib
+
+[BuildOptions]
+
+[Pcd]
+ gHisiTokenSpaceGuid.PcdCpldBaseAddress
diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c
new file mode 100644
index 0000000000..d3275276c2
--- /dev/null
+++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c
@@ -0,0 +1,104 @@
+/** @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 <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/CpldIoLib.h>
+
+UINTN mCpldRegAddr;
+EFI_EVENT mCpldVirtualAddressChangeEvent;
+
+
+VOID
+EFIAPI
+CpldVirtualAddressChange (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0, (VOID **) &mCpldRegAddr);
+
+ return;
+}
+
+RETURN_STATUS
+EFIAPI
+CpldRuntimeLibConstructor (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0};
+
+ mCpldRegAddr = PcdGet64(PcdCpldBaseAddress);
+ Status = gDS->GetMemorySpaceDescriptor(mCpldRegAddr,&desp);
+ if(EFI_ERROR(Status)){
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL] GetMemorySpaceDescriptor failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+ desp.Attributes |= EFI_MEMORY_RUNTIME;
+ Status = gDS->SetMemorySpaceAttributes(mCpldRegAddr,0x10000, desp.Attributes);
+ if(EFI_ERROR(Status)){
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL] SetMemorySpaceAttributes failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+ //
+ // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ CpldVirtualAddressChange,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mCpldVirtualAddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+CpldRuntimeLibDestructor (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if(!mCpldVirtualAddressChangeEvent ){
+ return Status;
+ }
+
+ Status = gBS->CloseEvent(mCpldVirtualAddressChangeEvent);
+ return Status;
+}
+
+VOID WriteCpldReg(UINTN ulRegAddr, UINT8 ulValue)
+{
+ MmioWrite8 (ulRegAddr + mCpldRegAddr, ulValue);
+}
+
+UINT8 ReadCpldReg(UINTN ulRegAddr)
+{
+ return MmioRead8 (ulRegAddr + mCpldRegAddr);
+}
+
+
diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf
new file mode 100644
index 0000000000..34c464f4f0
--- /dev/null
+++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf
@@ -0,0 +1,51 @@
+#/** @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 = CpldIoLibRuntime
+ FILE_GUID = C0939398-4AF5-43d0-B6FF-37996D642C04
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpldIoLib
+ CONSTRUCTOR = CpldRuntimeLibConstructor
+ DESTRUCTOR = CpldRuntimeLibDestructor
+
+[Sources.common]
+ CpldIoLibRuntime.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+
+[LibraryClasses]
+ UefiRuntimeLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ DebugLib
+ IoLib
+ BaseLib
+ TimerLib
+ PcdLib
+
+[BuildOptions]
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+[Pcd]
+ gHisiTokenSpaceGuid.PcdCpldBaseAddress
diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h
new file mode 100644
index 0000000000..d1e6c41dd7
--- /dev/null
+++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h
@@ -0,0 +1,178 @@
+/** @file
+*
+* Copyright (c) 2011, 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 the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+**/
+
+
+#ifndef __DS3231_REAL_TIME_CLOCK_H__
+#define __DS3231_REAL_TIME_CLOCK_H__
+
+#define DS3231_REGADDR_SECONDS 0x00
+#define DS3231_REGADDR_MIUTES 0x01
+#define DS3231_REGADDR_HOURS 0x02
+#define DS3231_REGADDR_DAY 0x03
+#define DS3231_REGADDR_DATE 0x04
+#define DS3231_REGADDR_MONTH 0x05
+#define DS3231_REGADDR_YEAR 0x06
+#define DS3231_REGADDR_ALARM1SEC 0x07
+#define DS3231_REGADDR_ALARM1MIN 0x08
+#define DS3231_REGADDR_ALARM1HOUR 0x09
+#define DS3231_REGADDR_ALARM1DAY 0x0A
+#define DS3231_REGADDR_ALARM2MIN 0x0B
+#define DS3231_REGADDR_ALARM2HOUR 0x0C
+#define DS3231_REGADDR_ALARM2DAY 0x0D
+#define DS3231_REGADDR_CONTROL 0x0E
+#define DS3231_REGADDR_STATUS 0x0F
+#define DS3231_REGADDR_AGOFFSET 0x10
+#define DS3231_REGADDR_TEMPMSB 0x11
+#define DS3231_REGADDR_TEMPLSB 0x12
+
+
+typedef union {
+ struct{
+ UINT8 A1IE:1;
+ UINT8 A2IE:1;
+ UINT8 INTCN:1;
+ UINT8 RSV:2;
+ UINT8 CONV:1;
+ UINT8 BBSQW:1;
+ UINT8 EOSC_N:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_CONTROL;
+
+typedef union {
+ struct{
+ UINT8 A1F:1;
+ UINT8 A2F:1;
+ UINT8 BSY:1;
+ UINT8 EN32KHZ:2;
+ UINT8 Rsv:3;
+ UINT8 OSF:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_STATUS;
+
+
+typedef union {
+ struct{
+ UINT8 Data:7;
+ UINT8 Sign:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_AGOFFSET;
+
+typedef union {
+ struct{
+ UINT8 Data:7;
+ UINT8 Sign:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_TEMPMSB;
+
+
+typedef union {
+ struct{
+ UINT8 Rsv:6;
+ UINT8 Data:2;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_TEMPLSB;
+
+typedef union {
+ struct{
+ UINT8 Seconds:4;
+ UINT8 Seconds10:3;
+ UINT8 Rsv:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_SECONDS;
+
+typedef union {
+ struct{
+ UINT8 Minutes:4;
+ UINT8 Minutes10:3;
+ UINT8 Rsv:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_MINUTES;
+
+typedef union {
+ struct{
+ UINT8 Hour:4;
+ UINT8 Hours10:1;
+ UINT8 PM_20Hours:1;
+ UINT8 Hour24_n:1;
+ UINT8 Rsv:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_HOURS;
+
+typedef union {
+ struct{
+ UINT8 Day:3;
+ UINT8 Rsv:5;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_DAY;
+
+typedef union {
+ struct{
+ UINT8 Month:4;
+ UINT8 Month10:1;
+ UINT8 Rsv:2;
+ UINT8 Century:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_MONTH;
+
+typedef union {
+ struct{
+ UINT8 Year:4;
+ UINT8 Year10:4;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_YEAR;
+
+typedef union {
+ struct{
+ UINT8 Seconds:4;
+ UINT8 Seconds10:3;
+ UINT8 A1M1:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_ALARM1SEC;
+
+typedef union {
+ struct{
+ UINT8 Minutes:4;
+ UINT8 Minutes10:3;
+ UINT8 A1M2:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_ALARM1MIN;
+
+typedef union {
+ struct{
+ UINT8 Hour:4;
+ UINT8 Hours10:1;
+ UINT8 PM_20Hours:1;
+ UINT8 Hours24:1;
+ UINT8 A1M3:1;
+ }bits;
+ UINT8 u8;
+}RTC_DS3231_ALARM1HOUR;
+
+#endif
diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c
new file mode 100644
index 0000000000..02d6d7f14d
--- /dev/null
+++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c
@@ -0,0 +1,433 @@
+/** @file
+ Implement EFI RealTimeClock runtime services via RTC Lib.
+
+ Currently this driver does not support runtime virtual calling.
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2011-2013, ARM Ltd. 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 the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+
+**/
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+// Use EfiAtRuntime to check stage
+#include <Library/UefiRuntimeLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/TimeBaseLib.h>
+#include <Protocol/RealTimeClock.h>
+#include <Library/I2CLib.h>
+#include "DS3231RealTimeClock.h"
+
+extern I2C_DEVICE gDS3231RtcDevice;
+
+STATIC BOOLEAN mDS3231Initialized = FALSE;
+
+EFI_STATUS
+IdentifyDS3231 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ return Status;
+}
+
+EFI_STATUS
+InitializeDS3231 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ I2C_DEVICE Dev;
+ RTC_DS3231_CONTROL Temp;
+ RTC_DS3231_HOURS Hours;
+
+ // Prepare the hardware
+ (VOID)IdentifyDS3231();
+
+ (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev));
+
+ Status = I2CInit(Dev.Socket,Dev.Port,Normal);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ // Ensure interrupts are masked. We do not want RTC interrupts in UEFI
+ Status = I2CRead(&Dev,DS3231_REGADDR_CONTROL,1,&Temp.u8);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ Temp.bits.INTCN = 0;
+ Status = I2CWrite(&Dev,DS3231_REGADDR_CONTROL,1,&Temp.u8);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ MicroSecondDelay(2000);
+ Status = I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Hours.u8);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ Hours.bits.Hour24_n = 0;
+ Status = I2CWrite(&Dev,DS3231_REGADDR_HOURS,1,&Hours.u8);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+
+ mDS3231Initialized = TRUE;
+
+ EXIT:
+ return Status;
+}
+
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 Temp;
+ UINT8 BaseHour = 0;
+ UINT16 BaseYear = 1900;
+
+ I2C_DEVICE Dev;
+
+ // Ensure Time is a valid pointer
+ if (NULL == Time) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize the hardware if not already done
+ if (!mDS3231Initialized) {
+ Status = InitializeDS3231 ();
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_READY;
+ }
+ }
+
+ (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev));
+
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_MONTH,1,&Temp);
+
+ Time->Month = ((Temp>>4)&1)*10+(Temp&0x0F);
+
+
+ if(Temp&0x80){
+ BaseYear = 2000;
+ }
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_YEAR,1,&Temp);
+
+ Time->Year = BaseYear+(Temp>>4) *10 + (Temp&0x0F);
+
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_DATE,1,&Temp);
+
+ Time->Day = ((Temp>>4)&3) *10 + (Temp&0x0F);
+
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Temp);
+
+ BaseHour = 0;
+ if((Temp&0x30) == 0x30){
+ return EFI_DEVICE_ERROR;
+ }else if(Temp&0x20){
+ BaseHour = 20;
+ }else if(Temp&0x10){
+ BaseHour = 10;
+ }
+ Time->Hour = BaseHour + (Temp&0x0F);
+
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_MIUTES,1,&Temp);
+
+ Time->Minute = ((Temp>>4)&7) * 10 + (Temp&0x0F);
+
+
+ Status |= I2CRead(&Dev,DS3231_REGADDR_SECONDS,1,&Temp);
+
+ Time->Second = (Temp>>4) * 10 + (Temp&0x0F);
+
+ Time->Nanosecond = 0;
+ Time->Daylight = 0;
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+
+ if((EFI_ERROR(Status)) || (!IsTimeValid(Time)) || ((Time->Year - BaseYear) > 99)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ I2C_DEVICE Dev;
+ UINT8 Temp;
+ UINT16 BaseYear = 1900;
+
+ // Check the input parameters are within the range specified by UEFI
+ if(!IsTimeValid(Time)){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize the hardware if not already done
+ if (!mDS3231Initialized) {
+ Status = InitializeDS3231 ();
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+
+ (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev));
+
+ Temp = ((Time->Second/10)<<4) | (Time->Second%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_SECONDS,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ Temp = ((Time->Minute/10)<<4) | (Time->Minute%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_MIUTES,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ Temp = 0;
+ if(Time->Hour > 19){
+ Temp = 2;
+ } else if(Time->Hour > 9){
+ Temp = 1;
+ }
+ Temp = (Temp << 4) | (Time->Hour%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_HOURS,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ Temp = ((Time->Day/10)<<4) | (Time->Day%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_DATE,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ Temp = 0;
+ if(Time->Year >= 2000){
+ Temp = 0x8;
+ BaseYear = 2000;
+ }
+
+ if(Time->Month > 9){
+ Temp |= 0x1;
+ }
+ Temp = (Temp<<4) | (Time->Month%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_MONTH,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ Temp = (((Time->Year-BaseYear)/10)<<4) | (Time->Year%10);
+ MicroSecondDelay(1000);
+ Status = I2CWrite(&Dev,DS3231_REGADDR_YEAR,1,&Temp);
+ if(EFI_ERROR (Status)){
+ goto EXIT;
+ }
+
+ EXIT:
+ return Status;
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+
+ EFI_TIME EfiTime;
+
+ // Setup the setters and getters
+ gRT->GetTime = LibGetTime;
+ gRT->SetTime = LibSetTime;
+ gRT->GetWakeupTime = LibGetWakeupTime;
+ gRT->SetWakeupTime = LibSetWakeupTime;
+
+ Status = gRT->GetTime (&EfiTime, NULL);
+ if(EFI_ERROR (Status) || (EfiTime.Year < 2000) || (EfiTime.Year > 2099)){
+ EfiTime.Year = 2000;
+ EfiTime.Month = 1;
+ EfiTime.Day = 1;
+ EfiTime.Hour = 0;
+ EfiTime.Minute = 0;
+ EfiTime.Second = 0;
+ EfiTime.Nanosecond = 0;
+ EfiTime.Daylight = 0;
+ EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+
+ Status = gRT->SetTime(&EfiTime);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, __LINE__, Status));
+ }
+ }
+
+ // Install the protocol
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiRealTimeClockArchProtocolGuid, NULL,
+ NULL
+ );
+
+ return Status;
+}
+
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.
+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses
+ // to virtual address. After the OS transitions to calling in virtual mode, all future
+ // runtime calls will be made in virtual mode.
+ //
+ return;
+}
diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf
new file mode 100644
index 0000000000..6faefb1128
--- /dev/null
+++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf
@@ -0,0 +1,48 @@
+#/** @file
+#
+# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011-2013, ARM Ltd. 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.
+#
+#
+# Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DS3231RealTimeClockLib
+ FILE_GUID = 470DFB96-E205-4515-A75E-2E60F853E79D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib
+
+[Sources.common]
+ DS3231RealTimeClockLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ UefiLib
+ DebugLib
+ PcdLib
+ I2CLib
+ TimeBaseLib
+ TimerLib
+# Use EFiAtRuntime to check stage
+ UefiRuntimeLib
+
+[Pcd]
+
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c
new file mode 100644
index 0000000000..ce70ca5ee1
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c
@@ -0,0 +1,302 @@
+/** @file
+ UART Serial Port library functions
+
+ Copyright (c) 2006 - 2009, Intel Corporation
+ Copyright (c) 2015 - 2016, Hisilicon Limited. All rights reserved.
+ Copyright (c) 2015 - 2016, Linaro Limited. All rights reserved.
+ 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 the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+**/
+#include <Uefi.h>
+#include <Library/PcdLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/SerialIo.h>
+
+#include "Dw8250SerialPortLib.h"
+
+
+/**
+ Initialize the serial device hardware.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+ If the serial device was successfuly initialized, then return RETURN_SUCCESS.
+ If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+ @retval RETURN_SUCCESS The serial device was initialized.
+ @retval RETURN_DEVICE_ERROR The serail device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINT32 ulUartClkFreq;
+
+ MmioWrite8 (UART_LCR_REG, UART_LCR_DLS8);
+ MmioWrite8 (UART_FCR_REG, UART_FCR_EN | UART_FCR_RXCLR | UART_FCR_TXCLR);
+ MmioWrite8 (UART_LCR_REG, UART_LCR_DLAB | UART_LCR_DLS8);
+
+ ulUartClkFreq = PcdGet32(PcdUartClkInHz);
+
+ MmioWrite8 (UART_DLL_REG, (ulUartClkFreq / (16 * (UINT32)BAUDRATE) ) & 0xff);
+ MmioWrite8 (UART_DLH_REG, ((ulUartClkFreq/ (16 * (UINT32)BAUDRATE) ) >> 8 ) & 0xff);
+ MmioWrite8 (UART_LCR_REG, UART_LCR_DLS8);
+ MmioWrite8 (UART_IEL_REG, 0x00);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Write data from buffer to serial device.
+
+ Writes NumberOfBytes data bytes from Buffer to the serial device.
+ The number of bytes actually written to the serial device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+
+ If Buffer is NULL, then ASSERT().
+
+ If NumberOfBytes is zero, then return 0.
+
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+
+ SerialPortWriteChar(*Buffer);
+ Buffer++;
+ }
+
+ return Result;
+}
+
+
+/**
+ Reads data from a serial device into a buffer.
+
+ @param Buffer Pointer to the data buffer to store the data read from the serial device.
+ @param NumberOfBytes Number of bytes to read from the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes read from the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ Result = 0;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready.
+ //
+ *Buffer=SerialPortReadChar();
+ Buffer++ ;
+ Result++;
+ }
+
+ return Result;
+}
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+
+ Polls aserial device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+
+ return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR);
+
+}
+
+
+VOID SerialPortWriteChar(UINT8 scShowChar)
+{
+ UINT32 ulLoop = 0;
+
+ while(ulLoop < (UINT32)UART_SEND_DELAY)
+ {
+
+ if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02)
+ {
+ break;
+ }
+
+ ulLoop++;
+ }
+ MmioWrite8 (UART_THR_REG, (UINT8)scShowChar);
+
+ ulLoop = 0;
+ while(ulLoop < (UINT32)UART_SEND_DELAY)
+ {
+ if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04)
+ {
+ break;
+ }
+ ulLoop++;
+ }
+
+ return;
+}
+
+
+UINT8 SerialPortReadChar(VOID)
+{
+ UINT8 recvchar = 0;
+
+ while(1)
+ {
+ if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR)
+ {
+ break;
+ }
+ }
+
+ recvchar = MmioRead8 (UART_RBR_REG);
+
+ return recvchar;
+}
+
+/**
+ Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+ data bits, and stop bits on a serial device.
+
+ @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
+ device's default interface speed.
+ On output, the value actually set.
+ @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
+ serial interface. A ReceiveFifoDepth value of 0 will use
+ the device's default FIFO depth.
+ On output, the value actually set.
+ @param Timeout The requested time out for a single character in microseconds.
+ This timeout applies to both the transmit and receive side of the
+ interface. A Timeout value of 0 will use the device's default time
+ out value.
+ On output, the value actually set.
+ @param Parity The type of parity to use on this serial device. A Parity value of
+ DefaultParity will use the device's default parity value.
+ On output, the value actually set.
+ @param DataBits The number of data bits to use on the serial device. A DataBits
+ vaule of 0 will use the device's default data bit setting.
+ On output, the value actually set.
+ @param StopBits The number of stop bits to use on this serial device. A StopBits
+ value of DefaultStopBits will use the device's default number of
+ stop bits.
+ On output, the value actually set.
+
+ @retval RETURN_SUCCESS The new attributes were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetAttributes (
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT UINT32 *Timeout,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
+
+/**
+ Set the serial device control bits.
+
+ @param Control Control bits which are to be set on the serial device.
+
+ @retval EFI_SUCCESS The new control bits were set on the serial device.
+ @retval EFI_UNSUPPORTED The serial device does not support this operation.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get the serial device control bits.
+
+ @param Control Control signals read from the serial device.
+
+ @retval EFI_SUCCESS The control bits were read from the serial device.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+
+ if (SerialPortPoll ()) {
+ // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY
+ *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ } else {
+ *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h
new file mode 100644
index 0000000000..5e80257289
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h
@@ -0,0 +1,116 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015-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.
+*
+* Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+**/
+
+#ifndef __DW8250_SERIALPORTLIB_H__
+#define __DW8250_SERIALPORTLIB_H__
+
+
+#define SERIAL_0_BASE_ADR (PcdGet64(PcdSerialRegisterBase))
+
+
+#define UART_SEND_DELAY (PcdGet32(PcdSerialPortSendDelay))
+#define BAUDRATE (PcdGet64(PcdUartDefaultBaudRate))
+
+
+#define UART_THR_REG (SERIAL_0_BASE_ADR + UART_THR)
+#define UART_RBR_REG (SERIAL_0_BASE_ADR + UART_RBR)
+#define UART_DLL_REG (SERIAL_0_BASE_ADR + UART_DLL)
+#define UART_DLH_REG (SERIAL_0_BASE_ADR + UART_DLH)
+#define UART_IEL_REG (SERIAL_0_BASE_ADR + UART_IEL)
+#define UART_IIR_REG (SERIAL_0_BASE_ADR + UART_IIR)
+#define UART_FCR_REG (SERIAL_0_BASE_ADR + UART_FCR)
+#define UART_LCR_REG (SERIAL_0_BASE_ADR + UART_LCR)
+#define UART_LSR_REG (SERIAL_0_BASE_ADR + UART_LSR)
+#define UART_USR_REG (SERIAL_0_BASE_ADR + UART_USR)
+
+
+#define UART_RBR 0x00
+#define UART_THR 0x00
+#define UART_DLL 0x00
+#define UART_DLH 0x04
+#define UART_IEL 0x04
+#define UART_IIR 0x08
+#define UART_FCR 0x08
+#define UART_LCR 0x0C
+#define UART_MCR 0x10
+#define UART_LSR 0x14
+#define UART_USR 0x7C
+
+/* register definitions */
+
+#define UART_FCR_EN 0x01
+#define UART_FCR_RXCLR 0x02
+#define UART_FCR_TXCLR 0x04
+#define UART_FCR_CLEARFIFO 0x00
+#define UART_FCR_RXL1 0x00
+#define UART_FCR_RXL4 0x40
+#define UART_FCR_RXL8 0x80
+#define UART_FCR_RXL14 0xc0
+#define UART_FCR_TXL0 0x00
+#define UART_FCR_TXL4 0x20
+#define UART_FCR_TXL8 0x30
+#define UART_FCR_TXL14 0x10
+
+/*LCR Name: Line Control Register fields*/
+#define UART_LCR_DLAB 0x80
+#define UART_LCR_EPS 0x10
+#define UART_LCR_PEN 0x08
+#define UART_LCR_STOP 0x04
+#define UART_LCR_DLS8 0x03
+#define UART_LCR_DLS7 0x02
+#define UART_LCR_DLS6 0x01
+#define UART_LCR_DLS5 0x00
+
+
+#define UART_DLH_AND_DLL_WIDTH 0xFF
+
+
+#define UART_IER_PTIME 0x80
+#define UART_IER_ELSI 0x04
+#define UART_IER_ETBEI 0x02
+#define UART_IER_ERBFI 0x01
+
+
+#define UART_IIR_FIFOSE 0xC0
+
+
+#define UART_IIR_InterruptID 0x01
+#define UART_IIR_INTIDTE 0x02
+#define UART_IIR_INTIDRA 0x04
+#define UART_IIR_INTIDRLS 0x06
+#define UART_IIR_INTMASK 0x0f
+#define UART_IIR_RDA 0x04
+#define UART_IIR_TE 0x02
+
+#define UART_LSR_TEMT 0x40
+#define UART_LSR_THRE 0x20
+#define UART_LSR_BI 0x10
+#define UART_LSR_FE 0x08
+#define UART_LSR_PE 0x04
+#define UART_LSR_R 0x02
+#define UART_LSR_DR 0x01
+
+
+#define UART_USR_BUSY 0x01
+
+#define FIFO_MAXSIZE 32
+
+extern UINT8 SerialPortReadChar(VOID);
+extern VOID SerialPortWriteChar(UINT8 scShowChar);
+
+#endif
+
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf
new file mode 100644
index 0000000000..d7957ea499
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf
@@ -0,0 +1,45 @@
+#/** @file
+#
+# Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.<BR>
+# Copyright (c) 2015-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.
+#
+# Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Dw8250SerialPortLib
+ FILE_GUID = 16D53E86-7EA6-47bd-861F-511ED9B8ABE0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+
+[Sources.common]
+ Dw8250SerialPortLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gHisiTokenSpaceGuid.PcdSerialPortSendDelay
+ gHisiTokenSpaceGuid.PcdUartClkInHz
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c
new file mode 100644
index 0000000000..d092659228
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c
@@ -0,0 +1,356 @@
+/** @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 the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+**/
+#include <Uefi.h>
+#include <PiDxe.h>
+
+#include <Library/PcdLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+
+#include <Protocol/SerialIo.h>
+#include <Guid/EventGroup.h>
+#include "Dw8250SerialPortRuntimeLib.h"
+
+UINT64 mSerialRegBaseAddr = 0;
+
+EFI_EVENT mSerialVirtualAddressChangeEvent = NULL;
+
+VOID
+EFIAPI
+SerialVirtualAddressChangeCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0, (VOID **) &mSerialRegBaseAddr);
+
+ return;
+}
+
+
+EFI_STATUS
+EFIAPI
+SerialPortLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if(!mSerialVirtualAddressChangeEvent ){
+ return Status;
+ }
+
+ Status = gBS->CloseEvent(mSerialVirtualAddressChangeEvent);
+ return Status;
+}
+
+/**
+ Initialize the serial device hardware.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+ If the serial device was successfuly initialized, then return RETURN_SUCCESS.
+ If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+ @retval RETURN_SUCCESS The serial device was initialized.
+ @retval RETURN_DEVICE_ERROR The serail device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0};
+
+ mSerialRegBaseAddr = PcdGet64(PcdSerialRegisterBase);
+
+ Status = gDS->GetMemorySpaceDescriptor(PcdGet64(PcdSerialRegisterBase),&desp);
+ if(EFI_ERROR(Status)){
+ return Status;
+ }
+ desp.Attributes |= EFI_MEMORY_RUNTIME;
+ Status = gDS->SetMemorySpaceAttributes(PcdGet64(PcdSerialRegisterBase),PcdGet64(PcdSerialRegisterSpaceSize), desp.Attributes);
+ if(EFI_ERROR(Status)){
+ return Status;
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SerialVirtualAddressChangeCallBack,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mSerialVirtualAddressChangeEvent
+ );
+
+ if(EFI_ERROR(Status)){
+ mSerialVirtualAddressChangeEvent = NULL;
+ }
+
+ return Status;
+}
+
+
+/**
+ Write data from buffer to serial device.
+
+ Writes NumberOfBytes data bytes from Buffer to the serial device.
+ The number of bytes actually written to the serial device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+
+ If Buffer is NULL, then ASSERT().
+
+ If NumberOfBytes is zero, then return 0.
+
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ Result = NumberOfBytes;
+
+ while (NumberOfBytes--) {
+
+ SerialPortWriteChar(*Buffer);
+ Buffer++;
+ }
+
+ return Result;
+}
+
+
+/**
+ Reads data from a serial device into a buffer.
+
+ @param Buffer Pointer to the data buffer to store the data read from the serial device.
+ @param NumberOfBytes Number of bytes to read from the serial device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes read from the serial device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Result;
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ Result = 0;
+
+ while (NumberOfBytes--) {
+ //
+ // Wait for the serail port to be ready.
+ //
+ *Buffer=SerialPortReadChar();
+ Buffer++ ;
+ Result++;
+ }
+
+ return Result;
+}
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+
+ Polls aserial device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+
+ return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR);
+
+}
+
+
+VOID SerialPortWriteChar(UINT8 scShowChar)
+{
+ UINT32 ulLoop = 0;
+
+ while(ulLoop < (UINT32)UART_SEND_DELAY)
+ {
+
+ if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02)
+ {
+ break;
+ }
+
+ ulLoop++;
+ }
+ MmioWrite8 (UART_THR_REG, (UINT8)scShowChar);
+
+ ulLoop = 0;
+ while(ulLoop < (UINT32)UART_SEND_DELAY)
+ {
+ if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04)
+ {
+ break;
+ }
+ ulLoop++;
+ }
+
+ return;
+}
+
+
+UINT8 SerialPortReadChar(VOID)
+{
+ UINT8 recvchar = 0;
+
+ do
+ {
+ if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR) {
+ break;
+ }
+
+ }while(MmioRead8 (UART_USR_REG) & UART_USR_BUSY);
+
+ recvchar = MmioRead8 (UART_RBR_REG);
+
+ return recvchar;
+}
+
+/**
+ Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+ data bits, and stop bits on a serial device.
+
+ @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
+ device's default interface speed.
+ On output, the value actually set.
+ @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
+ serial interface. A ReceiveFifoDepth value of 0 will use
+ the device's default FIFO depth.
+ On output, the value actually set.
+ @param Timeout The requested time out for a single character in microseconds.
+ This timeout applies to both the transmit and receive side of the
+ interface. A Timeout value of 0 will use the device's default time
+ out value.
+ On output, the value actually set.
+ @param Parity The type of parity to use on this serial device. A Parity value of
+ DefaultParity will use the device's default parity value.
+ On output, the value actually set.
+ @param DataBits The number of data bits to use on the serial device. A DataBits
+ vaule of 0 will use the device's default data bit setting.
+ On output, the value actually set.
+ @param StopBits The number of stop bits to use on this serial device. A StopBits
+ value of DefaultStopBits will use the device's default number of
+ stop bits.
+ On output, the value actually set.
+
+ @retval RETURN_SUCCESS The new attributes were set on the serial device.
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetAttributes (
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT UINT32 *Timeout,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
+
+/**
+ Set the serial device control bits.
+
+ @param Control Control bits which are to be set on the serial device.
+
+ @retval EFI_SUCCESS The new control bits were set on the serial device.
+ @retval EFI_UNSUPPORTED The serial device does not support this operation.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get the serial device control bits.
+
+ @param Control Control signals read from the serial device.
+
+ @retval EFI_SUCCESS The control bits were read from the serial device.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+
+ if (SerialPortPoll ()) {
+ // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY
+ *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ } else {
+ *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h
new file mode 100644
index 0000000000..f5dcb9ec8d
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h
@@ -0,0 +1,116 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015-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.
+*
+* Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+**/
+
+#ifndef __DW8250_SERIALPORTLIB_H__
+#define __DW8250_SERIALPORTLIB_H__
+
+
+#define SERIAL_0_BASE_ADR (mSerialRegBaseAddr)
+
+
+#define UART_SEND_DELAY (PcdGet32(PcdSerialPortSendDelay))
+#define BAUDRATE (PcdGet64(PcdUartDefaultBaudRate))
+
+
+#define UART_THR_REG (SERIAL_0_BASE_ADR + UART_THR)
+#define UART_RBR_REG (SERIAL_0_BASE_ADR + UART_RBR)
+#define UART_DLL_REG (SERIAL_0_BASE_ADR + UART_DLL)
+#define UART_DLH_REG (SERIAL_0_BASE_ADR + UART_DLH)
+#define UART_IEL_REG (SERIAL_0_BASE_ADR + UART_IEL)
+#define UART_IIR_REG (SERIAL_0_BASE_ADR + UART_IIR)
+#define UART_FCR_REG (SERIAL_0_BASE_ADR + UART_FCR)
+#define UART_LCR_REG (SERIAL_0_BASE_ADR + UART_LCR)
+#define UART_LSR_REG (SERIAL_0_BASE_ADR + UART_LSR)
+#define UART_USR_REG (SERIAL_0_BASE_ADR + UART_USR)
+
+
+#define UART_RBR 0x00
+#define UART_THR 0x00
+#define UART_DLL 0x00
+#define UART_DLH 0x04
+#define UART_IEL 0x04
+#define UART_IIR 0x08
+#define UART_FCR 0x08
+#define UART_LCR 0x0C
+#define UART_MCR 0x10
+#define UART_LSR 0x14
+#define UART_USR 0x7C
+
+/* register definitions */
+
+#define UART_FCR_EN 0x01
+#define UART_FCR_RXCLR 0x02
+#define UART_FCR_TXCLR 0x04
+#define UART_FCR_CLEARFIFO 0x00
+#define UART_FCR_RXL1 0x00
+#define UART_FCR_RXL4 0x40
+#define UART_FCR_RXL8 0x80
+#define UART_FCR_RXL14 0xc0
+#define UART_FCR_TXL0 0x00
+#define UART_FCR_TXL4 0x20
+#define UART_FCR_TXL8 0x30
+#define UART_FCR_TXL14 0x10
+
+/*LCR Name: Line Control Register fields*/
+#define UART_LCR_DLAB 0x80
+#define UART_LCR_EPS 0x10
+#define UART_LCR_PEN 0x08
+#define UART_LCR_STOP 0x04
+#define UART_LCR_DLS8 0x03
+#define UART_LCR_DLS7 0x02
+#define UART_LCR_DLS6 0x01
+#define UART_LCR_DLS5 0x00
+
+
+#define UART_DLH_AND_DLL_WIDTH 0xFF
+
+
+#define UART_IER_PTIME 0x80
+#define UART_IER_ELSI 0x04
+#define UART_IER_ETBEI 0x02
+#define UART_IER_ERBFI 0x01
+
+
+#define UART_IIR_FIFOSE 0xC0
+
+
+#define UART_IIR_InterruptID 0x01
+#define UART_IIR_INTIDTE 0x02
+#define UART_IIR_INTIDRA 0x04
+#define UART_IIR_INTIDRLS 0x06
+#define UART_IIR_INTMASK 0x0f
+#define UART_IIR_RDA 0x04
+#define UART_IIR_TE 0x02
+
+#define UART_LSR_TEMT 0x40
+#define UART_LSR_THRE 0x20
+#define UART_LSR_BI 0x10
+#define UART_LSR_FE 0x08
+#define UART_LSR_PE 0x04
+#define UART_LSR_R 0x02
+#define UART_LSR_DR 0x01
+
+
+#define UART_USR_BUSY 0x01
+
+#define FIFO_MAXSIZE 32
+
+extern UINT8 SerialPortReadChar(VOID);
+extern VOID SerialPortWriteChar(UINT8 scShowChar);
+
+#endif
+
diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf
new file mode 100644
index 0000000000..2cedcb1004
--- /dev/null
+++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+# Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.<BR>
+# Copyright (c) 2015-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.
+#
+# Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Dw8250SerialPortLib
+ FILE_GUID = 16D53E86-7EA6-47bd-861F-511ED9B8ABE0
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+ DESTRUCTOR = SerialPortLibDestructor
+
+[Sources.common]
+ Dw8250SerialPortRuntimeLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ UefiRuntimeLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+ gHisiTokenSpaceGuid.PcdSerialRegisterSpaceSize
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gHisiTokenSpaceGuid.PcdSerialPortSendDelay
+ gHisiTokenSpaceGuid.PcdUartClkInHz
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CHw.h b/Silicon/Hisilicon/Library/I2CLib/I2CHw.h
new file mode 100644
index 0000000000..aa561e929c
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CHw.h
@@ -0,0 +1,269 @@
+/** @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 _I2C_HW_H_
+#define _I2C_HW_H_
+
+#include <Uefi.h>
+#include <Library/IoLib.h>
+
+#define I2C_READ_TIMEOUT 500
+#define I2C_DRV_ONCE_WRITE_BYTES_NUM 8
+#define I2C_DRV_ONCE_READ_BYTES_NUM 8
+#define I2C_READ_SIGNAL 0x0100
+#define I2C_TXRX_THRESHOLD 0x7
+#define I2C_SS_SCLHCNT 0x493
+#define I2C_SS_SCLLCNT 0x4fe
+#define I2C_CMD_STOP_BIT BIT9
+
+#define I2C_REG_WRITE(reg,data) \
+ MmioWrite32 ((reg), (data))
+
+#define I2C_REG_READ(reg,result) \
+ (result) = MmioRead32 ((reg))
+
+ #define I2C_CON_OFFSET 0x0
+ #define I2C_TAR_OFFSET 0x4
+ #define I2C_SAR_OFFSET 0x8
+ #define I2C_DATA_CMD_OFFSET 0x10
+ #define I2C_SS_SCL_HCNT_OFFSET 0x14
+ #define I2C_SS_SCL_LCNT_OFFSET 0x18
+ #define I2C_FS_SCL_HCNT_OFFSET 0x1c
+ #define I2C_FS_SCL_LCNT_OFFSET 0x20
+ #define I2C_INTR_STAT_OFFSET 0x2c
+ #define I2C_INTR_MASK_OFFSET 0x30
+ #define I2C_RAW_INTR_STAT_OFFSET 0x34
+ #define I2C_RX_TL_OFFSET 0x38
+ #define I2C_TX_TL_OFFSET 0x3c
+ #define I2C_CLR_INTR_OFFSET 0x40
+ #define I2C_CLR_RX_UNDER_OFFSET 0x44
+ #define I2C_CLR_RX_OVER_OFFSET 0x48
+ #define I2C_CLR_TX_OVER_OFFSET 0x4c
+ #define I2C_CLR_RD_REQ_OFFSET 0x50
+ #define I2C_CLR_TX_ABRT_OFFSET 0x54
+ #define I2C_CLR_RX_DONE_OFFSET 0x58
+ #define I2C_CLR_ACTIVITY_OFFSET 0x5c
+ #define I2C_CLR_STOP_DET_OFFSET 0x60
+ #define I2C_CLR_START_DET_OFFSET 0x64
+ #define I2C_CLR_GEN_CALL_OFFSET 0x68
+ #define I2C_ENABLE_OFFSET 0x6c
+ #define I2C_STATUS_OFFSET 0x70
+ #define I2C_TXFLR_OFFSET 0x74
+ #define I2C_RXFLR_OFFSET 0x78
+ #define I2C_SDA_HOLD 0x7c
+ #define I2C_TX_ABRT_SOURCE_OFFSET 0x80
+ #define I2C_SLV_DATA_ONLY_OFFSET 0x84
+ #define I2C_DMA_CR_OFFSET 0x88
+ #define I2C_DMA_TDLR_OFFSET 0x8c
+ #define I2C_DMA_RDLR_OFFSET 0x90
+ #define I2C_SDA_SETUP_OFFSET 0x94
+ #define I2C_ACK_GENERAL_CALL_OFFSET 0x98
+ #define I2C_ENABLE_STATUS_OFFSET 0x9c
+
+
+ typedef union tagI2c0Con
+ {
+ struct
+ {
+ UINT32 master : 1 ;
+ UINT32 spedd : 2 ;
+ UINT32 slave_10bit : 1 ;
+ UINT32 master_10bit : 1 ;
+ UINT32 restart_en : 1 ;
+ UINT32 slave_disable : 1 ;
+ UINT32 Reserved_0 : 25 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_CON_U;
+
+
+ typedef union tagI2c0Tar
+ {
+ struct
+ {
+ UINT32 ic_tar : 10 ;
+ UINT32 gc_or_start : 1 ;
+ UINT32 special : 1 ;
+ UINT32 ic_10bitaddr_master : 1 ;
+ UINT32 Reserved_1 : 19 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_TAR_U;
+
+
+ typedef union tagI2c0DataCmd
+ {
+ struct
+ {
+ UINT32 dat : 8 ;
+ UINT32 cmd : 1 ;
+ UINT32 Reserved_5 : 23 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_DATA_CMD_U;
+
+
+ typedef union tagI2c0SsSclHcnt
+ {
+ struct
+ {
+ UINT32 ic_ss_scl_hcnt : 16 ;
+ UINT32 Reserved_7 : 16 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_SS_SCL_HCNT_U;
+
+
+ typedef union tagI2c0SsSclLcnt
+ {
+ struct
+ {
+ UINT32 ic_ss_scl_lcnt : 16 ;
+ UINT32 Reserved_9 : 16 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_SS_SCL_LCNT_U;
+
+
+ typedef union tagI2c0FsSclHcnt
+ {
+ struct
+ {
+ UINT32 ic_fs_scl_hcnt : 16 ;
+ UINT32 Reserved_11 : 16 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_FS_SCL_HCNT_U;
+
+
+ typedef union tagI2c0FsSclLcnt
+ {
+ struct
+ {
+ UINT32 ic_fs_scl_lcnt : 16 ;
+ UINT32 Reserved_13 : 16 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_FS_SCL_LCNT_U;
+
+
+ typedef union tagI2c0IntrMask
+ {
+ struct
+ {
+ UINT32 m_rx_under : 1 ;
+ UINT32 m_rx_over : 1 ;
+ UINT32 m_rx_full : 1 ;
+ UINT32 m_tx_over : 1 ;
+ UINT32 m_tx_empty : 1 ;
+ UINT32 m_rd_req : 1 ;
+ UINT32 m_tx_abrt : 1 ;
+ UINT32 m_rx_done : 1 ;
+ UINT32 m_activity : 1 ;
+ UINT32 m_stop_det : 1 ;
+ UINT32 m_start_det : 1 ;
+ UINT32 m_gen_call : 1 ;
+ UINT32 Reserved_17 : 20 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_INTR_MASK_U;
+
+
+ typedef union tagI2c0RxTl
+ {
+ struct
+ {
+ UINT32 rx_tl : 8 ;
+ UINT32 Reserved_21 : 24 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_RX_TL_U;
+
+
+ typedef union tagI2c0TxTl
+ {
+ struct
+ {
+ UINT32 tx_tl : 8 ;
+ UINT32 Reserved_23 : 24 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_TX_TL_U;
+
+
+ typedef union tagI2c0Enable
+ {
+ struct
+ {
+ UINT32 enable : 1 ;
+ UINT32 Reserved_47 : 31 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_ENABLE_U;
+
+
+ typedef union tagI2c0Status
+ {
+ struct
+ {
+ UINT32 activity : 1 ;
+ UINT32 tfnf : 1 ;
+ UINT32 tfe : 1 ;
+ UINT32 rfne : 1 ;
+ UINT32 rff : 1 ;
+ UINT32 mst_activity : 1 ;
+ UINT32 slv_activity : 1 ;
+ UINT32 Reserved_49 : 25 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_STATUS_U;
+
+
+ typedef union tagI2c0Txflr
+ {
+ struct
+ {
+ UINT32 txflr : 4 ;
+ UINT32 Reserved_51 : 28 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_TXFLR_U;
+
+
+ typedef union tagI2c0Rxflr
+ {
+ struct
+ {
+ UINT32 rxflr : 4 ;
+ UINT32 Reserved_53 : 28 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_RXFLR_U;
+
+
+ typedef union tagI2c0EnableStatus
+ {
+ struct
+ {
+ UINT32 ic_en : 1 ;
+ UINT32 slv_disable_while_busy: 1 ;
+ UINT32 slv_rx_data_lost : 1 ;
+ UINT32 Reserved_69 : 29 ;
+ } bits;
+ UINT32 Val32;
+ } I2C0_ENABLE_STATUS_U;
+
+
+#endif
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLib.c b/Silicon/Hisilicon/Library/I2CLib/I2CLib.c
new file mode 100644
index 0000000000..b5b388d756
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLib.c
@@ -0,0 +1,655 @@
+/** @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/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/I2CLib.h>
+#include <Library/TimerLib.h>
+
+#include <Library/PlatformSysCtrlLib.h>
+
+#include "I2CLibInternal.h"
+#include "I2CHw.h"
+
+VOID I2C_Delay(UINT32 ulCount)
+{
+ MicroSecondDelay(ulCount);
+ return;
+}
+
+
+EFI_STATUS
+EFIAPI
+I2C_Disable(UINT32 Socket,UINT8 Port)
+{
+ UINT32 ulTimeCnt = I2C_READ_TIMEOUT;
+ I2C0_STATUS_U I2cStatusReg;
+ I2C0_ENABLE_U I2cEnableReg;
+ I2C0_ENABLE_STATUS_U I2cEnableStatusReg;
+
+ UINTN Base = GetI2cBase(Socket, Port);
+
+ I2C_REG_READ((Base + I2C_STATUS_OFFSET), I2cStatusReg.Val32);
+
+ while (I2cStatusReg.bits.activity)
+ {
+ I2C_Delay(10000);
+
+ ulTimeCnt--;
+ I2C_REG_READ(Base + I2C_STATUS_OFFSET, I2cStatusReg.Val32);
+ if (0 == ulTimeCnt)
+ {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+
+ I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
+ I2cEnableReg.bits.enable = 0;
+ I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET,I2cEnableReg.Val32);
+
+ I2C_REG_READ(Base + I2C_ENABLE_OFFSET,I2cEnableStatusReg.Val32);
+ if (0 == I2cEnableStatusReg.bits.ic_en)
+ {
+ return EFI_SUCCESS;
+ }
+ else
+ {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+
+EFI_STATUS
+EFIAPI
+I2C_Enable(UINT32 Socket,UINT8 Port)
+{
+ I2C0_ENABLE_U I2cEnableReg;
+ I2C0_ENABLE_STATUS_U I2cEnableStatusReg;
+
+ UINTN Base = GetI2cBase(Socket, Port);
+
+
+ I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
+ I2cEnableReg.bits.enable = 1;
+ I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
+
+
+ I2C_REG_READ(Base + I2C_ENABLE_STATUS_OFFSET, I2cEnableStatusReg.Val32);
+ if (1 == I2cEnableStatusReg.bits.ic_en)
+ {
+ return EFI_SUCCESS;
+ }
+ else
+ {
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+void I2C_SetTarget(UINT32 Socket,UINT8 Port,UINT32 I2cDeviceAddr)
+{
+ I2C0_TAR_U I2cTargetReg;
+ UINTN Base = GetI2cBase(Socket, Port);
+
+
+ I2C_REG_READ(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32);
+ I2cTargetReg.bits.ic_tar = I2cDeviceAddr;
+ I2C_REG_WRITE(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32);
+
+ return;
+}
+
+
+EFI_STATUS
+EFIAPI
+I2CInit(UINT32 Socket, UINT32 Port, SPEED_MODE SpeedMode)
+{
+ I2C0_CON_U I2cControlReg;
+ I2C0_SS_SCL_HCNT_U I2cStandardSpeedSclHighCount;
+ I2C0_SS_SCL_LCNT_U I2cStandardSpeedSclLowCount;
+ I2C0_RX_TL_U I2cRxFifoReg;
+ I2C0_TX_TL_U I2cTxFifoReg;
+ I2C0_INTR_MASK_U I2cIntrMask;
+ EFI_STATUS Status;
+
+ UINTN Base = GetI2cBase(Socket, Port);
+
+ if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX) || (SpeedMode >= SPEED_MODE_MAX)){
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ Status = I2C_Disable(Socket,Port);
+ if(EFI_ERROR(Status))
+ {
+ return EFI_DEVICE_ERROR;
+ }
+
+
+ I2C_REG_READ(Base + I2C_CON_OFFSET, I2cControlReg.Val32);
+ I2cControlReg.bits.master = 1;
+ I2cControlReg.bits.spedd = 0x1;
+ I2cControlReg.bits.restart_en = 1;
+ I2cControlReg.bits.slave_disable = 1;
+ I2C_REG_WRITE(Base + I2C_CON_OFFSET,I2cControlReg.Val32);
+
+
+ if(Normal == SpeedMode)
+ {
+ I2C_REG_READ(Base + I2C_SS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32);
+ I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT;
+ I2C_REG_WRITE(Base + I2C_SS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32);
+ I2C_REG_READ(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
+ I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT;
+ I2C_REG_WRITE(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
+ }
+ else
+ {
+ I2C_REG_READ(Base + I2C_FS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32);
+ I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT;
+ I2C_REG_WRITE(Base + I2C_FS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32);
+ I2C_REG_READ(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
+ I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT;
+ I2C_REG_WRITE(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
+ }
+
+
+ I2C_REG_READ(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32);
+ I2cRxFifoReg.bits.rx_tl = I2C_TXRX_THRESHOLD;
+ I2C_REG_WRITE(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32);
+ I2C_REG_READ(Base + I2C_TX_TL_OFFSET,I2cTxFifoReg.Val32);
+ I2cTxFifoReg.bits.tx_tl = I2C_TXRX_THRESHOLD;
+ I2C_REG_WRITE(Base + I2C_TX_TL_OFFSET, I2cTxFifoReg.Val32);
+
+
+ I2C_REG_READ(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32);
+ I2cIntrMask.Val32 = 0x0;
+ I2C_REG_WRITE(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32);
+
+
+ Status = I2C_Enable(Socket,Port);
+ if(EFI_ERROR(Status))
+ {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return I2cLibRuntimeSetup (Socket, Port);
+}
+
+EFI_STATUS
+EFIAPI
+I2CSdaConfig(UINT32 Socket, UINT32 Port)
+{
+
+ UINTN Base = GetI2cBase(Socket, Port);
+
+ if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX)){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ I2C_REG_WRITE(Base + I2C_SDA_HOLD, 0x14);
+
+ return EFI_SUCCESS;
+}
+
+
+
+UINT32 I2C_GetTxStatus(UINT32 Socket,UINT8 Port)
+{
+ I2C0_TXFLR_U ulFifo;
+ UINTN Base = GetI2cBase(Socket, Port);
+
+ I2C_REG_READ(Base + I2C_TXFLR_OFFSET, ulFifo.Val32);
+ return ulFifo.bits.txflr;
+}
+
+UINT32
+I2C_GetRxStatus(UINT32 Socket,UINT8 Port)
+{
+ I2C0_RXFLR_U ulFifo;
+ UINTN Base = GetI2cBase(Socket, Port);
+
+ I2C_REG_READ(Base + I2C_RXFLR_OFFSET, ulFifo.Val32);
+ return ulFifo.bits.rxflr;
+}
+
+EFI_STATUS
+EFIAPI
+WriteBeforeRead(I2C_DEVICE *I2cInfo, UINT32 ulLength, UINT8 *pBuf)
+{
+ UINT32 ulFifo;
+ UINT32 ulCnt;
+ UINT32 ulTimes = 0;
+
+ UINTN Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
+
+
+ I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ for(ulCnt = 0; ulCnt < ulLength; ulCnt++)
+ {
+ ulTimes = 0;
+ while(ulFifo > I2C_TXRX_THRESHOLD)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++);
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ ulTimes = 0;
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+I2CWrite(I2C_DEVICE *I2cInfo, UINT16 InfoOffset, UINT32 ulLength, UINT8 *pBuf)
+{
+ UINT32 ulFifo;
+ UINT32 ulTimes = 0;
+ UINT32 Idx;
+ UINTN Base;
+
+
+ if(I2cInfo->Port >= I2C_PORT_MAX)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
+
+ (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
+
+ I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+
+ if(I2cInfo->DeviceType)
+ {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
+ }
+ else
+ {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
+ }
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ ulTimes = 0;
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ for(Idx = 0; Idx < ulLength; Idx++)
+ {
+ ulTimes = 0;
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ while(ulFifo > I2C_TXRX_THRESHOLD)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ if (Idx < ulLength - 1) {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++));
+ } else {
+ //Send command stop bit for the last transfer
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++) | I2C_CMD_STOP_BIT);
+ }
+ }
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ ulTimes = 0;
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n"));
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+I2CRead(I2C_DEVICE *I2cInfo, UINT16 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf)
+{
+ UINT32 ulFifo;
+ UINT32 ulTimes = 0;
+ UINT8 I2CWAddr[2];
+ EFI_STATUS Status;
+ UINT32 Idx = 0;
+ UINTN Base;
+
+
+ if(I2cInfo->Port >= I2C_PORT_MAX)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
+ Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
+ if(I2cInfo->DeviceType)
+ {
+ I2CWAddr[0] = (InfoOffset >> 8) & 0xff;
+ I2CWAddr[1] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+ else
+ {
+ I2CWAddr[0] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+
+ I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+
+ while(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+ while (ulRxLen > 0) {
+ if (ulRxLen > 1) {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL);
+ } else {
+ //Send command stop bit for the last transfer
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL | I2C_CMD_STOP_BIT);
+ }
+
+ ulTimes = 0;
+ do {
+ I2C_Delay(2);
+
+ while(++ulTimes > I2C_READ_TIMEOUT) {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }while(0 == ulFifo);
+
+ I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]);
+
+ ulRxLen --;
+ }
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+I2CReadMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf)
+{
+ UINT32 ulCnt;
+ UINT16 usTotalLen = 0;
+ UINT32 ulFifo;
+ UINT32 ulTimes = 0;
+ UINT8 I2CWAddr[4];
+ EFI_STATUS Status;
+ UINT32 BytesLeft;
+ UINT32 Idx = 0;
+ UINTN Base;
+
+
+ if(I2cInfo->Port >= I2C_PORT_MAX)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
+ Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
+ if(I2cInfo->DeviceType == DEVICE_TYPE_E2PROM)
+ {
+ I2CWAddr[0] = (InfoOffset >> 8) & 0xff;
+ I2CWAddr[1] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+
+ else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS)
+ {
+ I2CWAddr[0] = (InfoOffset >> 16) & 0xff;
+ I2CWAddr[1] = (InfoOffset >> 8) & 0xff;
+ I2CWAddr[2] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 3,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+
+ else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS)
+ {
+ I2CWAddr[0] = (InfoOffset >> 24) & 0xff;
+ I2CWAddr[1] = (InfoOffset >> 16) & 0xff;
+ I2CWAddr[2] = (InfoOffset >> 8) & 0xff;
+ I2CWAddr[3] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 4,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+
+ else
+ {
+ I2CWAddr[0] = (InfoOffset & 0xff);
+ Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr);
+ if(EFI_ERROR(Status))
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_ABORTED;
+ }
+ }
+
+
+ I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
+ usTotalLen = ulRxLen;
+ BytesLeft = usTotalLen;
+
+ for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL);
+ }
+
+
+ for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) {
+ ulTimes = 0;
+ do {
+ I2C_Delay(2);
+
+ while(++ulTimes > I2C_READ_TIMEOUT) {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }while(0 == ulFifo);
+
+ I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]);
+ }
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+I2CWriteMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset, UINT32 ulLength, UINT8 *pBuf)
+{
+ UINT32 ulFifo;
+ UINT32 ulTimes = 0;
+ UINT32 Idx;
+ UINTN Base;
+
+
+ if(I2cInfo->Port >= I2C_PORT_MAX)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
+
+ (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
+
+ I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+
+
+ if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS)
+ {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
+ }
+
+ else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS)
+ {
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 24) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
+ }
+
+ else
+ {
+
+ }
+
+ ulTimes = 0;
+ for(Idx = 0; Idx < ulLength; Idx++)
+ {
+
+ I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++);
+
+ }
+
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ ulTimes = 0;
+ while(0 != ulFifo)
+ {
+ I2C_Delay(2);
+
+ if(++ulTimes > I2C_READ_TIMEOUT)
+ {
+ DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n"));
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+ return EFI_TIMEOUT;
+ }
+ ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
+ }
+ (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf b/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf
new file mode 100644
index 0000000000..7f9512467a
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf
@@ -0,0 +1,49 @@
+#/** @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 = I2CLib
+ FILE_GUID = FC5651CA-55D8-4fd2-B6D3-A284D993ABA2
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = I2CLib
+
+[Sources.common]
+ I2CLib.c
+ I2CLibCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ BaseLib
+ ArmLib
+ TimerLib
+
+ PlatformSysCtrlLib
+
+[BuildOptions]
+
+[Pcd]
+
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c b/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c
new file mode 100644
index 0000000000..499c2d7a22
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c
@@ -0,0 +1,35 @@
+/** @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/BaseLib.h>
+
+#include <Library/PlatformSysCtrlLib.h>
+#include "I2CLibInternal.h"
+
+UINTN GetI2cBase (UINT32 Socket, UINT8 Port)
+{
+ return PlatformGetI2cBase(Socket, Port);
+}
+
+EFI_STATUS
+I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port)
+{
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h b/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h
new file mode 100644
index 0000000000..14297296e9
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h
@@ -0,0 +1,29 @@
+/** @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 _I2C_LIB_INTERNAL_H_
+#define _I2C_LIB_INTERNAL_H_
+
+#include <PlatformArch.h>
+#include <Library/I2CLib.h>
+
+UINTN GetI2cBase (UINT32 Socket, UINT8 Port);
+
+EFI_STATUS
+I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port);
+
+
+#endif
+
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c
new file mode 100644
index 0000000000..678b5a0082
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c
@@ -0,0 +1,109 @@
+/** @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/BaseLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/PlatformSysCtrlLib.h>
+#include "I2CLibInternal.h"
+
+STATIC EFI_EVENT mI2cLibVirtualAddrChangeEvent;
+
+STATIC UINTN gI2cBase[MAX_SOCKET][I2C_PORT_MAX];
+
+UINTN GetI2cBase (UINT32 Socket, UINT8 Port)
+{
+ if (gI2cBase[Socket][Port] == 0) {
+ gI2cBase[Socket][Port] = PlatformGetI2cBase(Socket, Port);
+ }
+
+ return gI2cBase[Socket][Port];
+}
+
+VOID
+EFIAPI
+I2cLibVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 Socket;
+ UINT8 Port;
+
+ // We assume that all I2C ports used in one runtime driver need to be
+ // converted into virtual address.
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ for (Port = 0; Port < I2C_PORT_MAX; Port++) {
+ if (gI2cBase[Socket][Port] != 0) {
+ EfiConvertPointer (0x0, (VOID **)&gI2cBase[Socket][Port]);
+ }
+ }
+ }
+
+ return;
+}
+
+EFI_STATUS
+I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port)
+{
+ EFI_STATUS Status;
+
+ UINTN Base = GetI2cBase (Socket, Port);
+
+ // Declare the controller as EFI_MEMORY_RUNTIME
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Base, SIZE_64KB,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_WARN, "[%a:%d] AddMemorySpace failed: %r\n", __FUNCTION__, __LINE__, Status));
+ }
+
+ Status = gDS->SetMemorySpaceAttributes (Base, SIZE_64KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] SetMemorySpaceAttributes failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ // Only create event once
+ if (mI2cLibVirtualAddrChangeEvent == NULL) {
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ I2cLibVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mI2cLibVirtualAddrChangeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] Create event failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf
new file mode 100644
index 0000000000..4990072558
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf
@@ -0,0 +1,51 @@
+#/** @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 = I2CLibRuntime
+ FILE_GUID = FC5651CA-55D8-4fd2-B6D3-A284D993ABA2
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = I2CLib
+
+[Sources.common]
+ I2CLib.c
+ I2CLibRuntime.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ BaseLib
+ ArmLib
+ TimerLib
+ DxeServicesTableLib
+ UefiRuntimeLib
+
+ PlatformSysCtrlLib
+
+[BuildOptions]
+
+[Pcd]
+
diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
new file mode 100644
index 0000000000..dc23e46c1f
--- /dev/null
+++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
@@ -0,0 +1,963 @@
+/** @file
+ Implementation for PlatformBdsLib library class interfaces.
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2004 - 2008, 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.
+
+ Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/
+
+**/
+
+#include <IndustryStandard/Pci22.h>
+#include <Library/DevicePathLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Library/IpmiCmdLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformBdsLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Guid/GlobalVariable.h>
+
+#include "IntelBdsPlatform.h"
+
+GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99,
+ 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} };
+
+//3CEF354A-3B7A-4519-AD70-72A134698311
+GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70,
+ 0x72, 0xA1, 0x34, 0x69, 0x83, 0x11} };
+
+// Need to keep the same with FlashStartOs.inf
+// 282cae50-940e-11e5-b7b8-774201c0f2d8
+GUID gFlashStartOsAppGuid = { 0x282cae50, 0x940e, 0x11e5, {0xb7, 0xb8,
+ 0x77, 0x42, 0x01, 0xc0, 0xf2, 0xd8} };
+
+// Need to keep the same with EslStartOs.inf
+// 8880a72c-9411-11e5-b6f0-97310bc151d1
+GUID gEslStartOsAppGuid = { 0x8880a72c, 0x9411, 0x11e5, {0xb6, 0xf0,
+ 0x97, 0x31, 0x0b, 0xc1, 0x51, 0xd1} };
+
+EFI_STATUS
+BdsDeleteAllInvalidEfiBootOption (
+ VOID
+ );
+
+#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
+
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH SerialDxe;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEFINED_DEVICE_PATH Vt100;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_SERIAL_CONSOLE;
+#pragma pack ()
+
+#define SERIAL_DXE_FILE_GUID { \
+ 0xD3987D4B, 0x971A, 0x435F, \
+ { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
+ }
+
+STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
+ //
+ // VENDOR_DEVICE_PATH SerialDxe
+ //
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
+ SERIAL_DXE_FILE_GUID
+ },
+
+ //
+ // UART_DEVICE_PATH Uart
+ //
+ {
+ { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
+ 0, // Reserved
+ FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
+ FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
+ FixedPcdGet8 (PcdUartDefaultParity), // Parity
+ FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
+ },
+
+ //
+ // VENDOR_DEFINED_DEVICE_PATH Vt100
+ //
+ {
+ {
+ MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
+ DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
+ },
+ EFI_VT_100_GUID
+ },
+
+ //
+ // EFI_DEVICE_PATH_PROTOCOL End
+ //
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+
+#pragma pack (1)
+typedef struct {
+ USB_CLASS_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_USB_KEYBOARD;
+#pragma pack ()
+
+STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
+ //
+ // USB_CLASS_DEVICE_PATH Keyboard
+ //
+ {
+ {
+ MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
+ DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
+ },
+ 0xFFFF, // VendorId: any
+ 0xFFFF, // ProductId: any
+ 3, // DeviceClass: HID
+ 1, // DeviceSubClass: boot
+ 1 // DeviceProtocol: keyboard
+ },
+
+ //
+ // EFI_DEVICE_PATH_PROTOCOL End
+ //
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+STATIC
+UINT16
+GetBBSTypeFromFileSysPath (
+ IN CHAR16 *UsbPathTxt,
+ IN CHAR16 *FileSysPathTxt,
+ IN EFI_DEVICE_PATH_PROTOCOL *FileSysPath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+
+ if (StrnCmp (UsbPathTxt, FileSysPathTxt, StrLen (UsbPathTxt)) == 0) {
+ Node = FileSysPath;
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (Node) == MEDIA_CDROM_DP)) {
+ return BBS_TYPE_CDROM;
+ }
+ Node = NextDevicePathNode (Node);
+ }
+ }
+
+ return BBS_TYPE_UNKNOWN;
+}
+
+STATIC
+UINT16
+GetBBSTypeFromUsbPath (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *UsbPath
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *FileSystemHandles;
+ UINTN NumberFileSystemHandles;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *FileSysPath;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+ CHAR16 *UsbPathTxt;
+ CHAR16 *FileSysPathTxt;
+ UINT16 Result;
+
+ Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevPathToText);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status));
+ return BBS_TYPE_UNKNOWN;
+ }
+
+ Result = BBS_TYPE_UNKNOWN;
+ UsbPathTxt = DevPathToText->ConvertDevicePathToText (UsbPath, TRUE, TRUE);
+ if (UsbPathTxt == NULL) {
+ return Result;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NumberFileSystemHandles,
+ &FileSystemHandles
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Locate SimpleFileSystemProtocol error(%r)\n", Status));
+ FreePool (UsbPathTxt);
+ return BBS_TYPE_UNKNOWN;
+ }
+
+ for (Index = 0; Index < NumberFileSystemHandles; Index++) {
+ FileSysPath = DevicePathFromHandle (FileSystemHandles[Index]);
+ FileSysPathTxt = DevPathToText->ConvertDevicePathToText (FileSysPath, TRUE, TRUE);
+
+ if (FileSysPathTxt == NULL) {
+ continue;
+ }
+
+ Result = GetBBSTypeFromFileSysPath (UsbPathTxt, FileSysPathTxt, FileSysPath);
+ FreePool (FileSysPathTxt);
+
+ if (Result != BBS_TYPE_UNKNOWN) {
+ break;
+ }
+ }
+
+ if (NumberFileSystemHandles != 0) {
+ FreePool (FileSystemHandles);
+ }
+
+ FreePool (UsbPathTxt);
+
+ return Result;
+}
+
+STATIC
+UINT16
+GetBBSTypeFromMessagingDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *Node
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+ UINT16 Result;
+
+ Result = BBS_TYPE_UNKNOWN;
+
+ switch (DevicePathSubType (Node)) {
+ case MSG_MAC_ADDR_DP:
+ Result = BBS_TYPE_EMBEDDED_NETWORK;
+ break;
+
+ case MSG_USB_DP:
+ Result = GetBBSTypeFromUsbPath (DevicePath);
+ if (Result == BBS_TYPE_UNKNOWN) {
+ Result = BBS_TYPE_USB;
+ }
+ break;
+
+ case MSG_SATA_DP:
+ Result = BBS_TYPE_HARDDRIVE;
+ break;
+
+ case MSG_VENDOR_DP:
+ Vendor = (VENDOR_DEVICE_PATH *) (Node);
+ if ((&Vendor->Guid) != NULL) {
+ if (CompareGuid (&Vendor->Guid, &((EFI_GUID) DEVICE_PATH_MESSAGING_SAS))) {
+ Result = BBS_TYPE_HARDDRIVE;
+ }
+ }
+ break;
+
+ default:
+ Result = BBS_TYPE_UNKNOWN;
+ break;
+ }
+
+ return Result;
+}
+
+STATIC
+UINT16
+GetBBSTypeByDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ UINT16 Result;
+
+ Result = BBS_TYPE_UNKNOWN;
+ if (DevicePath == NULL) {
+ return Result;
+ }
+
+ Node = DevicePath;
+ while (!IsDevicePathEnd (Node)) {
+ switch (DevicePathType (Node)) {
+ case MEDIA_DEVICE_PATH:
+ if (DevicePathSubType (Node) == MEDIA_CDROM_DP) {
+ Result = BBS_TYPE_CDROM;
+ }
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+ Result = GetBBSTypeFromMessagingDevicePath (DevicePath, Node);
+ break;
+
+ default:
+ Result = BBS_TYPE_UNKNOWN;
+ break;
+ }
+
+ if (Result != BBS_TYPE_UNKNOWN) {
+ break;
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+
+ return Result;
+}
+
+STATIC
+EFI_STATUS
+GetBmcBootOptionsSetting (
+ OUT IPMI_GET_BOOT_OPTION *BmcBootOpt
+ )
+{
+ EFI_STATUS Status;
+
+ Status = IpmiCmdGetSysBootOptions (BmcBootOpt);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Get iBMC BootOpts %r!\n", Status));
+ return Status;
+ }
+
+ if (BmcBootOpt->BootFlagsValid != BOOT_OPTION_BOOT_FLAG_VALID) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (BmcBootOpt->Persistent) {
+ BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_VALID;
+ } else {
+ BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_INVALID;
+ }
+
+ Status = IpmiCmdSetSysBootOptions (BmcBootOpt);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Set iBMC BootOpts %r!\n", Status));
+ }
+
+ return Status;
+}
+
+STATIC
+VOID
+RestoreBootOrder (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+
+ GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize);
+ if (BootOrder == NULL) {
+ return ;
+ }
+
+ Print (L"Restore BootOrder(%d).\n", BootOrderSize / sizeof (UINT16));
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BootOrderSize,
+ BootOrder
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SetVariable BootOrder %r!\n", Status));
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrderBackup",
+ &gOemBootVaraibleGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status));
+ }
+
+ FreePool (BootOrder);
+
+ return;
+}
+
+
+VOID
+RestoreBootOrderOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // restore BootOrder variable in normal condition.
+ RestoreBootOrder ();
+}
+
+STATIC
+VOID
+UpdateBootOrder (
+ IN UINT16 *NewOrder,
+ IN UINT16 *BootOrder,
+ IN UINTN BootOrderSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ Status = gRT->SetVariable (
+ L"BootOrderBackup",
+ &gOemBootVaraibleGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BootOrderSize,
+ BootOrder
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BootOrderSize,
+ NewOrder
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ // Register notify function to restore BootOrder variable on ReadyToBoot Event.
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RestoreBootOrderOnReadyToBoot,
+ NULL,
+ &gEfiEventReadyToBootGuid,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Create ready to boot event %r!\n", Status));
+ }
+
+ return;
+}
+
+STATIC
+VOID
+SetBootOrder (
+ IN UINT16 BootType
+ )
+{
+ UINT16 *NewOrder;
+ UINT16 *RemainBoots;
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ CHAR16 OptionName[sizeof ("Boot####")];
+ UINTN Index;
+ LIST_ENTRY BootOptionList;
+ BDS_COMMON_OPTION *Option;
+ UINTN SelectCnt;
+ UINTN RemainCnt;
+
+ InitializeListHead (&BootOptionList);
+
+ GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
+ if (BootOrder == NULL) {
+ return ;
+ }
+
+ NewOrder = AllocatePool (BootOrderSize);
+ RemainBoots = AllocatePool (BootOrderSize);
+ if ((NewOrder == NULL) || (RemainBoots == NULL)) {
+ DEBUG ((DEBUG_ERROR, "Out of resources."));
+ goto Exit;
+ }
+
+ SelectCnt = 0;
+ RemainCnt = 0;
+
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
+ Option = BdsLibVariableToOption (&BootOptionList, OptionName);
+ if (Option == NULL) {
+ DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index]));
+ continue;
+ }
+
+ if (GetBBSTypeByDevicePath (Option->DevicePath) == BootType) {
+ NewOrder[SelectCnt++] = BootOrder[Index];
+ } else {
+ RemainBoots[RemainCnt++] = BootOrder[Index];
+ }
+ }
+
+ if (SelectCnt != 0) {
+ // append RemainBoots to NewOrder
+ for (Index = 0; Index < RemainCnt; Index++) {
+ NewOrder[SelectCnt + Index] = RemainBoots[Index];
+ }
+
+ if (CompareMem (NewOrder, BootOrder, BootOrderSize) != 0) {
+ UpdateBootOrder (NewOrder, BootOrder, BootOrderSize);
+ }
+ }
+
+Exit:
+ FreePool (BootOrder);
+ if (NewOrder != NULL) {
+ FreePool (NewOrder);
+ }
+ if (RemainBoots != NULL) {
+ FreePool (RemainBoots);
+ }
+
+ return ;
+}
+
+STATIC
+VOID
+HandleBmcBootType (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ IPMI_GET_BOOT_OPTION BmcBootOpt;
+ UINT16 BootType;
+
+ Status = GetBmcBootOptionsSetting (&BmcBootOpt);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Print (L"Boot Type from BMC is %x\n", BmcBootOpt.BootDeviceSelector);
+
+ switch (BmcBootOpt.BootDeviceSelector) {
+ case ForcePxe:
+ BootType = BBS_TYPE_EMBEDDED_NETWORK;
+ break;
+
+ case ForcePrimaryRemovableMedia:
+ BootType = BBS_TYPE_USB;
+ break;
+
+ case ForceDefaultHardDisk:
+ BootType = BBS_TYPE_HARDDRIVE;
+ break;
+
+ case ForceDefaultCD:
+ BootType = BBS_TYPE_CDROM;
+ break;
+
+ default:
+ return;
+ }
+
+ SetBootOrder (BootType);
+}
+
+//
+// BDS Platform Functions
+//
+/**
+ Platform Bds init. Include the platform firmware vendor, revision
+ and so crc check.
+
+**/
+VOID
+EFIAPI
+PlatformBdsInit (
+ VOID
+ )
+{
+ //Signal EndofDxe Event
+ EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid);
+
+ // restore BootOrder variable if previous BMC boot override attempt
+ // left it in a modified state
+ RestoreBootOrder ();
+}
+
+
+/**
+ Check if the handle satisfies a particular condition.
+
+ @param[in] Handle The handle to check.
+ @param[in] ReportText A caller-allocated string passed in for reporting
+ purposes. It must never be NULL.
+
+ @retval TRUE The condition is satisfied.
+ @retval FALSE Otherwise. This includes the case when the condition could not
+ be fully evaluated due to an error.
+**/
+typedef
+BOOLEAN
+(EFIAPI *FILTER_FUNCTION) (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ );
+
+
+/**
+ Process a handle.
+
+ @param[in] Handle The handle to process.
+ @param[in] ReportText A caller-allocated string passed in for reporting
+ purposes. It must never be NULL.
+**/
+typedef
+VOID
+(EFIAPI *CALLBACK_FUNCTION) (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ );
+
+/**
+ Locate all handles that carry the specified protocol, filter them with a
+ callback function, and pass each handle that passes the filter to another
+ callback.
+
+ @param[in] ProtocolGuid The protocol to look for.
+
+ @param[in] Filter The filter function to pass each handle to. If this
+ parameter is NULL, then all handles are processed.
+
+ @param[in] Process The callback function to pass each handle to that
+ clears the filter.
+**/
+STATIC
+VOID
+FilterAndProcess (
+ IN EFI_GUID *ProtocolGuid,
+ IN FILTER_FUNCTION Filter OPTIONAL,
+ IN CALLBACK_FUNCTION Process
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN NoHandles;
+ UINTN Idx;
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,
+ NULL /* SearchKey */, &NoHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ //
+ // This is not an error, just an informative condition.
+ //
+ DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,
+ Status));
+ return;
+ }
+
+ ASSERT (NoHandles > 0);
+ for (Idx = 0; Idx < NoHandles; ++Idx) {
+ CHAR16 *DevicePathText;
+ STATIC CHAR16 Fallback[] = L"<device path unavailable>";
+
+ //
+ // The ConvertDevicePathToText() function handles NULL input transparently.
+ //
+ DevicePathText = ConvertDevicePathToText (
+ DevicePathFromHandle (Handles[Idx]),
+ FALSE, // DisplayOnly
+ FALSE // AllowShortcuts
+ );
+ if (DevicePathText == NULL) {
+ DevicePathText = Fallback;
+ }
+
+ if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {
+ Process (Handles[Idx], DevicePathText);
+ }
+
+ if (DevicePathText != Fallback) {
+ FreePool (DevicePathText);
+ }
+ }
+ gBS->FreePool (Handles);
+}
+
+
+/**
+ This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsPciDisplay (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo);
+ if (EFI_ERROR (Status)) {
+ //
+ // This is not an error worth reporting.
+ //
+ return FALSE;
+ }
+
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,
+ sizeof Pci / sizeof (UINT32), &Pci);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
+ return FALSE;
+ }
+
+ return IS_PCI_DISPLAY (&Pci);
+}
+
+
+/**
+ This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
+ the matching driver to produce all first-level child handles.
+**/
+STATIC
+VOID
+EFIAPI
+Connect (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->ConnectController (
+ Handle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all children
+ FALSE // Recursive
+ );
+ DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",
+ __FUNCTION__, ReportText, Status));
+}
+
+
+/**
+ This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
+ handle, and adds it to ConOut and ErrOut.
+**/
+STATIC
+VOID
+EFIAPI
+AddOutput (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = DevicePathFromHandle (Handle);
+ if (DevicePath == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",
+ __FUNCTION__, ReportText, Handle));
+ return;
+ }
+
+ Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,
+ ReportText, Status));
+ return;
+ }
+
+ Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,
+ ReportText, Status));
+ return;
+ }
+
+ DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,
+ ReportText));
+}
+
+
+/**
+ The function will execute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+ @param DriverOptionList The header of the driver option link list
+ @param BootOptionList The header of the boot option link list
+ @param ProcessCapsules A pointer to ProcessCapsules()
+ @param BaseMemoryTest A pointer to BaseMemoryTest()
+
+**/
+VOID
+EFIAPI
+PlatformBdsPolicyBehavior (
+ IN LIST_ENTRY *DriverOptionList,
+ IN LIST_ENTRY *BootOptionList,
+ IN PROCESS_CAPSULES ProcessCapsules,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Locate the PCI root bridges and make the PCI bus driver connect each,
+ // non-recursively. This will produce a number of child handles with PciIo on
+ // them.
+ //
+ FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
+
+ //
+ // Find all display class PCI devices (using the handles from the previous
+ // step), and connect them non-recursively. This should produce a number of
+ // child handles with GOPs on them.
+ //
+ FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
+
+ //
+ // Now add the device path of all handles with GOP on them to ConOut and
+ // ErrOut.
+ //
+ FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
+
+ //
+ // Add the hardcoded short-form USB keyboard device path to ConIn.
+ //
+ BdsLibUpdateConsoleVariable (L"ConIn",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);
+
+ //
+ // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
+ //
+ BdsLibUpdateConsoleVariable (L"ConIn",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+ BdsLibUpdateConsoleVariable (L"ConOut",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+ BdsLibUpdateConsoleVariable (L"ErrOut",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+
+ //
+ // Connect the consoles based on the above variables.
+ //
+ BdsLibConnectAllDefaultConsoles ();
+
+ //
+ // Show the splash screen.
+ //
+ EnableQuietBoot (PcdGetPtr (PcdLogoFile));
+
+ //
+ // Connect the rest of the devices.
+ //
+ BdsLibConnectAll ();
+
+ //
+ // Add memory test to convert memory above 4GB to be tested
+ //
+ Status = BaseMemoryTest (QUICK);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] - Base memory test failed: %r\n", __FUNCTION__, __LINE__, Status));
+ }
+
+ //
+ // Process QEMU's -kernel command line option. Note that the kernel booted
+ // this way should receive ACPI tables, which is why we connect all devices
+ // first (see above) -- PCI enumeration blocks ACPI table installation, if
+ // there is a PCI host.
+ //
+ //TryRunningQemuKernel ();
+
+ BdsLibEnumerateAllBootOption (BootOptionList);
+
+ // Add Flash Start OS and ESL Start OS boot option
+ (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gFlashStartOsAppGuid, L"Flash Start OS");
+ (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEslStartOsAppGuid, L"ESL Start OS");
+
+ // Add EBL as boot option
+ (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEblFileGuid, L"Embedded Boot Loader (EBL)");
+
+ // Remove EFI Misc Device Boot Options
+ BdsDeleteAllInvalidEfiBootOption ();
+
+ //SetBootOrderFromQemu (BootOptionList);
+ //
+ // The BootOrder variable may have changed, reload the in-memory list with
+ // it.
+ //
+ BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
+
+ //PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
+ Print (L"Press Enter to boot OS immediately.\n");
+ Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut));
+ PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE);
+ HandleBmcBootType ();
+}
+
+/**
+ Hook point after a boot attempt succeeds. We don't expect a boot option to
+ return, so the UEFI 2.0 specification defines that you will default to an
+ interactive mode and stop processing the BootOrder list in this case. This
+ is also a platform implementation and can be customized by IBV/OEM.
+
+ @param Option Pointer to Boot Option that succeeded to boot.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+{
+}
+
+/**
+ Hook point after a boot attempt fails.
+
+ @param Option Pointer to Boot Option that failed to boot.
+ @param Status Status returned from failed boot.
+ @param ExitData Exit data returned from failed boot.
+ @param ExitDataSize Exit data size returned from failed boot.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+{
+}
+
+/**
+ This function locks platform flash that is not allowed to be updated during normal boot path.
+ The flash layout is platform specific.
+**/
+VOID
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+{
+ return;
+}
diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h
new file mode 100644
index 0000000000..4a912627a9
--- /dev/null
+++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h
@@ -0,0 +1,61 @@
+/** @file
+ Head file for BDS Platform specific code
+
+ Copyright (c) 2004 - 2008, 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 the files under ArmVirtPkg/Library/PlatformIntelBdsLib/
+
+**/
+
+#ifndef _INTEL_BDS_PLATFORM_H_
+#define _INTEL_BDS_PLATFORM_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include "IntelBdsPlatformCommon.h"
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ );
+
+/**
+ Download the kernel, the initial ramdisk, and the kernel command line from
+ QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two
+ image files, and load and start the kernel from it.
+
+ The kernel will be instructed via its command line to load the initrd from
+ the same Simple FileSystem.
+
+ @retval EFI_NOT_FOUND Kernel image was not found.
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+ @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.
+
+ @return Error codes from any of the underlying
+ functions. On success, the function doesn't
+ return.
+**/
+EFI_STATUS
+EFIAPI
+TryRunningQemuKernel (
+ VOID
+ );
+
+#endif // _INTEL_BDS_PLATFORM_H
diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c
new file mode 100644
index 0000000000..9ea701db11
--- /dev/null
+++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c
@@ -0,0 +1,118 @@
+/** @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 "IntelBdsPlatform.h"
+#include <Library/UefiLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Protocol/FirmwareVolume2.h>
+
+VOID
+EFIAPI
+BdsLibBuildOptionFromApp (
+ IN EFI_HANDLE Handle,
+ IN OUT LIST_ENTRY *BdsBootOptionList,
+ IN GUID *FileGuid,
+ IN CHAR16 *Description
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;
+
+ DevicePath = DevicePathFromHandle (Handle);
+
+ //
+ // Build the shell device path
+ //
+ EfiInitializeFwVolDevicepathNode (&ShellNode, FileGuid);
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);
+
+ //
+ // Create and register the shell boot option
+ //
+ BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, Description, L"BootOrder");
+
+}
+EFI_STATUS
+EFIAPI
+HwBdsLibRegisterAppBootOption (
+ IN OUT LIST_ENTRY *BdsBootOptionList,
+ IN GUID *FileGuid,
+ IN CHAR16 *Description
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN FvHandleCount;
+ EFI_HANDLE *FvHandleBuffer;
+ EFI_FV_FILETYPE Type;
+ UINTN Size;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 AuthenticationStatus;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ UINTN Count = 0;
+
+ //
+ // Check if we have on flash shell
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &FvHandleCount,
+ &FvHandleBuffer
+ );
+ for (Index = 0; Index < FvHandleCount; Index++) {
+ gBS->HandleProtocol (
+ FvHandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+
+ Status = Fv->ReadFile (
+ Fv,
+ FileGuid,
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Skip if no shell file in the FV
+ //
+ continue;
+ }
+ //
+ // Build the shell boot option
+ //
+ BdsLibBuildOptionFromApp (FvHandleBuffer[Index], BdsBootOptionList,
+ FileGuid, Description);
+
+ Count++;
+ }
+
+ if (FvHandleCount != 0) {
+ FreePool (FvHandleBuffer);
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h
new file mode 100644
index 0000000000..73b901ab51
--- /dev/null
+++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h
@@ -0,0 +1,27 @@
+/** @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 _HW_BDS_LIB_H_
+#define _HW_BDS_LIB_H_
+
+EFI_STATUS
+EFIAPI
+HwBdsLibRegisterAppBootOption (
+ IN OUT LIST_ENTRY *BdsBootOptionList,
+ IN GUID *FileGuid,
+ IN CHAR16 *Description
+ );
+
+#endif
diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf
new file mode 100644
index 0000000000..0feec06392
--- /dev/null
+++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf
@@ -0,0 +1,84 @@
+## @file
+# Implementation for PlatformBdsLib library class interfaces.
+#
+# Copyright (C) 2015, Red Hat, Inc.
+# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2007 - 2014, 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.
+#
+# Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformIntelBdsLib
+ FILE_GUID = 46DF84EB-F603-4D39-99D8-E1E86B50BCC2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ IntelBdsPlatform.c
+ IntelBdsPlatformCommon.c
+
+[Packages]
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ GenericBdsLib
+ IpmiCmdLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[FixedPcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
+ gEfiEventReadyToBootGuid
+ gEfiFileInfoGuid
+ gEfiFileSystemInfoGuid
+ gEfiFileSystemVolumeLabelInfoIdGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiDevicePathToTextProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
diff --git a/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c
new file mode 100644
index 0000000000..1d93d7ebba
--- /dev/null
+++ b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c
@@ -0,0 +1,429 @@
+/** @file
+ Implement EFI RealTimeClock runtime services via RTC Lib.
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2011 - 2014, ARM Ltd. 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 the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+
+**/
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/TimeBaseLib.h>
+
+#include <Protocol/RealTimeClock.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/ArmArchTimer.h>
+
+STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PV660VirtualRtcTimeZone";
+STATIC CONST CHAR16 mDaylightVariableName[] = L"PV660VirtualRtcDaylight";
+STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;
+STATIC EFI_RUNTIME_SERVICES *mRT;
+
+
+STATIC INTN mEpochDiff = 0;
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT64 Temp;
+ UINT32 EpochSeconds;
+ INT16 TimeZone = 0;
+ UINT8 Daylight = 0;
+ UINTN Size;
+
+ // Ensure Time is a valid pointer
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ArmArchTimerReadReg(CntPct,&Temp);
+
+ // UINT32 force convertion for PC-LINT
+ EpochSeconds = mEpochDiff + Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz);
+
+ // Get the current time zone information from non-volatile storage
+ Size = sizeof (TimeZone);
+ Status = mRT->GetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&TimeZone
+ );
+
+ if (EFI_ERROR (Status)) {
+ ASSERT(Status != EFI_INVALID_PARAMETER);
+ ASSERT(Status != EFI_BUFFER_TOO_SMALL);
+
+ if (Status != EFI_NOT_FOUND)
+ goto EXIT;
+
+ // The time zone variable does not exist in non-volatile storage, so create it.
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ // Store it
+ Status = mRT->SetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time->TimeZone)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",
+ mTimeZoneVariableName,
+ Status
+ ));
+ goto EXIT;
+ }
+ } else {
+ // Got the time zone
+ Time->TimeZone = TimeZone;
+
+ // Check TimeZone bounds: -1440 to 1440 or 2047
+ if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440))
+ && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ }
+
+ // Adjust for the correct time zone
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ EpochSeconds += Time->TimeZone * SEC_PER_MIN;
+ }
+ }
+
+ // Get the current daylight information from non-volatile storage
+ Size = sizeof (Daylight);
+ Status = mRT->GetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&Daylight
+ );
+
+ if (EFI_ERROR (Status)) {
+ ASSERT(Status != EFI_INVALID_PARAMETER);
+ ASSERT(Status != EFI_BUFFER_TOO_SMALL);
+
+ if (Status != EFI_NOT_FOUND)
+ goto EXIT;
+
+ // The daylight variable does not exist in non-volatile storage, so create it.
+ Time->Daylight = 0;
+ // Store it
+ Status = mRT->SetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time->Daylight)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",
+ mDaylightVariableName,
+ Status
+ ));
+ goto EXIT;
+ }
+ } else {
+ // Got the daylight information
+ Time->Daylight = Daylight;
+
+ // Adjust for the correct period
+ if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {
+ // Convert to adjusted time, i.e. spring forwards one hour
+ EpochSeconds += SEC_PER_HOUR;
+ }
+ }
+
+ // Convert from internal 32-bit time to UEFI time
+ EpochToEfiTime (EpochSeconds, Time);
+
+ // Update the Capabilities info
+ if (Capabilities != NULL) {
+ Capabilities->Resolution = 1;
+ // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000
+
+ Capabilities->Accuracy = PcdGet32 (PcdArmArchTimerFreqInHz);
+ // FALSE: Setting the time does not clear the values below the resolution level
+ Capabilities->SetsToZero = FALSE;
+ }
+
+ EXIT:
+ return Status;
+}
+
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ )
+{
+ EFI_STATUS Status;
+ UINTN EpochSeconds;
+ UINTN Temp;
+
+ // Check the input parameters are within the range specified by UEFI
+ if (!IsTimeValid (Time)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ // Because the PL031 is a 32-bit counter counting seconds,
+ // the maximum time span is just over 136 years.
+ // Time is stored in Unix Epoch format, so it starts in 1970,
+ // Therefore it can not exceed the year 2106.
+ if ((Time->Year < 1970) || (Time->Year >= 2106)) {
+ Status = EFI_UNSUPPORTED;
+ goto EXIT;
+ }
+
+ EpochSeconds = EfiTimeToEpoch (Time);
+
+ // Adjust for the correct time zone, i.e. convert to UTC time zone
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ EpochSeconds -= Time->TimeZone * SEC_PER_MIN;
+ }
+
+ // TODO: Automatic Daylight activation
+
+ // Adjust for the correct period
+ if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {
+ // Convert to un-adjusted time, i.e. fall back one hour
+ EpochSeconds -= SEC_PER_HOUR;
+ }
+
+ ArmArchTimerReadReg(CntPct,&Temp);
+
+ // UINT32 force convertion for PC-LINT
+ mEpochDiff = EpochSeconds - Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz);
+
+ // The accesses to Variable Services can be very slow, because we may be writing to Flash.
+ // Do this after having set the RTC.
+
+ // Save the current time zone information into non-volatile storage
+ Status = mRT->SetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (Time->TimeZone),
+ (VOID *)&(Time->TimeZone)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",
+ mTimeZoneVariableName,
+ Status
+ ));
+ goto EXIT;
+ }
+
+ // Save the current daylight information into non-volatile storage
+ Status = mRT->SetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(Time->Daylight),
+ (VOID *)&(Time->Daylight)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",
+ mDaylightVariableName,
+ Status
+ ));
+ goto EXIT;
+ }
+
+ EXIT:
+ return Status;
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.
+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses
+ // to virtual address. After the OS transitions to calling in virtual mode, all future
+ // runtime calls will be made in virtual mode.
+ //
+ EfiConvertPointer (0x0, (VOID**)&mRT);
+ return;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ // Setup the setters and getters
+ gRT->GetTime = LibGetTime;
+ gRT->SetTime = LibSetTime;
+ gRT->GetWakeupTime = LibGetWakeupTime;
+ gRT->SetWakeupTime = LibSetWakeupTime;
+
+ mRT = gRT;
+
+ // Install the protocol
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiRealTimeClockArchProtocolGuid, NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ LibRtcVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mRtcVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf
new file mode 100644
index 0000000000..35c01bff4f
--- /dev/null
+++ b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf
@@ -0,0 +1,47 @@
+#/** @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 = RealTimeClockLibVirtual
+ FILE_GUID = 432B35C1-A0CC-4720-A4B9-1EFD70050107
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib
+
+[Sources.common]
+ RealTimeClockLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ OpenPlatformPkg/OpenPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ UefiLib
+ DebugLib
+ PcdLib
+ DxeServicesTableLib
+ TimeBaseLib
+ UefiRuntimeLib
+ ArmLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz