aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/ArmPlatformPkg
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/ArmPlatformPkg
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/ArmPlatformPkg')
-rw-r--r--roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec112
-rw-r--r--roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc121
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c876
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c394
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h101
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf49
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c123
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c1333
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h358
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf67
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c800
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c409
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.h43
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf45
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.c431
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.h42
-rw-r--r--roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf45
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/ArmPlatformLib.h139
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h62
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/LcdPlatformLib.h326
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h30
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/PL011UartClockLib.h25
-rw-r--r--roms/edk2/ArmPlatformPkg/Include/Library/PL011UartLib.h183
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c403
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h237
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf38
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/AArch64/ArmPlatformHelper.S45
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.S43
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.asm62
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.c142
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf42
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNullMem.c28
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/AArch64/ArmPlatformStackLib.S99
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.S98
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.asm118
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf34
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c174
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h84
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf39
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.c69
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf22
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.c145
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf22
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.c28
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf24
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c237
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf41
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.c23
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf24
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011Uart.h114
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.c472
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf38
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClock.h39
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c356
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf45
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c165
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h143
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf35
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointer.c48
-rw-r--r--roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf26
-rw-r--r--roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.c197
-rw-r--r--roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf60
-rw-r--r--roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c144
-rw-r--r--roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf69
-rw-r--r--roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.c24
-rw-r--r--roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf44
-rw-r--r--roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c101
-rw-r--r--roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.inf56
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/ArchPrePeiCore.c46
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Exception.S114
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Helper.S42
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/PrePeiCoreEntryPoint.S90
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/SwitchStack.S32
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c56
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S96
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.asm83
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.S73
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.asm89
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S32
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm32
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c148
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c57
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c144
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h72
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf76
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf70
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c34
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S116
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c23
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S124
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm142
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c99
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c32
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf107
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf103
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/PrePi.c214
-rw-r--r--roms/edk2/ArmPlatformPkg/PrePi/PrePi.h90
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/build_report.py48
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py96
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py225
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/firmware_volume.py328
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py328
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Ds5/system_table.py171
-rw-r--r--roms/edk2/ArmPlatformPkg/Scripts/Makefile81
104 files changed, 14324 insertions, 0 deletions
diff --git a/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec b/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec
new file mode 100644
index 000000000..696d636aa
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec
@@ -0,0 +1,112 @@
+#/** @file
+#
+# Copyright (c) 2011-2018, ARM Limited. All rights reserved.
+# Copyright (c) 2015, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = ArmPlatformPkg
+ PACKAGE_GUID = 3308e0a0-1d94-11e0-915c-0002a5d5c51b
+ PACKAGE_VERSION = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+ Include # Root include for the package
+
+[LibraryClasses]
+ ArmPlatformLib|Include/Library/ArmPlatformLib.h
+ LcdHwLib|Include/Library/LcdHwLib.h
+ LcdPlatformLib|Include/Library/LcdPlatformLib.h
+ NorFlashPlatformLib|Include/Library/NorFlashPlatformLib.h
+ PL011UartClockLib|Include/Library/PL011UartClockLib.h
+ PL011UartLib|Include/Library/PL011UartLib.h
+
+[Guids.common]
+ gArmPlatformTokenSpaceGuid = { 0x9c0aaed4, 0x74c5, 0x4043, { 0xb4, 0x17, 0xa3, 0x22, 0x38, 0x14, 0xce, 0x76 } }
+
+[PcdsFeatureFlag.common]
+ gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores|FALSE|BOOLEAN|0x00000004
+
+ gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked|FALSE|BOOLEAN|0x0000003C
+
+ # Disable the GOP controller on ExitBootServices(). By default the value is FALSE,
+ # we assume the OS will handle the FrameBuffer from the UEFI GOP information.
+ gArmPlatformTokenSpaceGuid.PcdGopDisableOnExitBootServices|FALSE|BOOLEAN|0x0000003D
+
+[PcdsFixedAtBuild.common]
+ gArmPlatformTokenSpaceGuid.PcdCoreCount|1|UINT32|0x00000039
+ gArmPlatformTokenSpaceGuid.PcdClusterCount|1|UINT32|0x00000038
+
+ # Stack for CPU Cores in Non Secure Mode
+ gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0|UINT64|0x00000009
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x10000|UINT32|0x00000037
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize|0x1000|UINT32|0x0000000A
+
+ # Size of the region used by UEFI in permanent memory (Reserved 128MB by default)
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x08000000|UINT32|0x00000015
+
+ #
+ # ARM Primecells
+ #
+
+ ## SP805 Watchdog
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase|0x0|UINT32|0x00000023
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogClockFrequencyInHz|32000|UINT32|0x00000021
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogInterrupt|0|UINT32|0x0000002E
+
+ ## PL011 UART
+ gArmPlatformTokenSpaceGuid.PL011UartClkInHz|24000000|UINT32|0x0000001F
+ gArmPlatformTokenSpaceGuid.PL011UartInteger|0|UINT32|0x00000020
+ gArmPlatformTokenSpaceGuid.PL011UartFractional|0|UINT32|0x0000002D
+ gArmPlatformTokenSpaceGuid.PL011UartInterrupt|0x00000000|UINT32|0x0000002F
+ gArmPlatformTokenSpaceGuid.PL011UartRegOffsetVariant|0|UINT8|0x0000003E
+
+ ## PL011 Serial Debug UART
+ gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase|0x00000000|UINT64|0x00000030
+ gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate|0x00000000|UINT64|0x00000031
+ gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz|0x00000000|UINT32|0x00000032
+
+ ## PL061 GPIO
+ gArmPlatformTokenSpaceGuid.PcdPL061GpioBase|0x0|UINT32|0x00000025
+
+ ## PL111 Lcd & HdLcd
+ gArmPlatformTokenSpaceGuid.PcdPL111LcdBase|0x0|UINT32|0x00000026
+ gArmPlatformTokenSpaceGuid.PcdArmHdLcdBase|0x0|UINT32|0x00000027
+
+ ## Default size for display modes upto 1920x1080 (1920 * 1080 * 4 Bytes Per Pixel)
+ gArmPlatformTokenSpaceGuid.PcdArmLcdDdrFrameBufferSize|0x7E9000|UINT32|0x00000043
+ ## If set, framebuffer memory will be reserved and mapped in the system RAM
+ gArmPlatformTokenSpaceGuid.PcdArmLcdDdrFrameBufferBase|0x0|UINT64|0x00000044
+
+ ## ARM Mali Display Processor DP500/DP550/DP650
+ gArmPlatformTokenSpaceGuid.PcdArmMaliDpBase|0x0|UINT64|0x00000050
+ gArmPlatformTokenSpaceGuid.PcdArmMaliDpMemoryRegionLength|0x0|UINT32|0x00000051
+
+ # Graphics Output Pixel format
+ # 0 : PixelRedGreenBlueReserved8BitPerColor
+ # 1 : PixelBlueGreenRedReserved8BitPerColor
+ # 2 : PixelBitMask
+ # Default is set to UEFI console font format PixelBlueGreenRedReserved8BitPerColor
+ gArmPlatformTokenSpaceGuid.PcdGopPixelFormat|0x00000001|UINT32|0x00000040
+
+ ## If set, this will swap settings for HDLCD RED_SELECT and BLUE_SELECT registers
+ gArmPlatformTokenSpaceGuid.PcdArmHdLcdSwapBlueRedSelect|FALSE|BOOLEAN|0x00000045
+
+[PcdsFixedAtBuild.common,PcdsDynamic.common]
+ ## PL031 RealTimeClock
+ gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0|UINT32|0x00000024
+ gArmPlatformTokenSpaceGuid.PcdPL031RtcPpmAccuracy|300000000|UINT32|0x00000022
+
+ gArmPlatformTokenSpaceGuid.PcdWatchdogCount|0x0|UINT32|0x00000033
diff --git a/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc b/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc
new file mode 100644
index 000000000..5381c95af
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc
@@ -0,0 +1,121 @@
+#/** @file
+# ARM platform package.
+#
+# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2016 - 2017, Linaro Ltd. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = ArmPlatformPkg
+ PLATFORM_GUID = 9ce08891-ac9c-476d-ab04-0c04d3a97544
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x0001001A
+ OUTPUT_DIRECTORY = Build/ArmPlatform
+ SUPPORTED_ARCHITECTURES = ARM|AARCH64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+[BuildOptions]
+ RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+ *_*_*_CC_FLAGS = -DDISABLE_NEW_DEPRECATED_INTERFACES
+
+[PcdsFixedAtBuild]
+ gArmTokenSpaceGuid.PcdFdBaseAddress|0x0
+ gArmTokenSpaceGuid.PcdFdSize|0x1000
+
+[LibraryClasses.common]
+ ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
+ ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
+ ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
+ ArmPlatformLib|ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
+ ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
+ ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ LcdHwLib|ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf
+ LcdPlatformLib|ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf
+ LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
+ NorFlashPlatformLib|ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
+ PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+
+[LibraryClasses.common.SEC]
+ ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
+ HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
+ MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf
+ PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
+
+[Components.common]
+ ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf
+ ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
+ ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
+ ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
+
+ ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
+ ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
+ ArmPlatformPkg/Library/HdLcd/HdLcd.inf
+ ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf
+ ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf
+ ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf
+ ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
+ ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
+ ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
+ ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+ ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf
+ ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
+
+ ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
+ ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
+
+ ArmPlatformPkg/PlatformPei/PlatformPeim.inf
+ ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
+
+ ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
+ ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
+
+ ArmPlatformPkg/PrePi/PeiMPCore.inf
+ ArmPlatformPkg/PrePi/PeiUniCore.inf
+
+ ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
new file mode 100644
index 000000000..c865215ec
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
@@ -0,0 +1,876 @@
+/** @file
+
+ Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#include <PiDxe.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+extern BOOLEAN mDisplayInitialized;
+
+//
+// Function Definitions
+//
+
+STATIC
+EFI_STATUS
+VideoCopyNoHorizontalOverlap (
+ IN UINTN BitsPerPixel,
+ IN volatile VOID *FrameBufferBase,
+ IN UINT32 HorizontalResolution,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN SourceLine;
+ UINTN DestinationLine;
+ UINTN WidthInBytes;
+ UINTN LineCount;
+ INTN Step;
+ VOID *SourceAddr;
+ VOID *DestinationAddr;
+
+ if( DestinationY <= SourceY ) {
+ // scrolling up (or horizontally but without overlap)
+ SourceLine = SourceY;
+ DestinationLine = DestinationY;
+ Step = 1;
+ } else {
+ // scrolling down
+ SourceLine = SourceY + Height;
+ DestinationLine = DestinationY + Height;
+ Step = -1;
+ }
+
+ switch (BitsPerPixel) {
+
+ case LCD_BITS_PER_PIXEL_24:
+
+ WidthInBytes = Width * 4;
+
+ for( LineCount = 0; LineCount < Height; LineCount++ ) {
+ // Update the start addresses of source & destination using 32bit pointer arithmetic
+ SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
+ DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+ // Copy the entire line Y from video ram to the temp buffer
+ CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+ // Update the line numbers
+ SourceLine += Step;
+ DestinationLine += Step;
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_555:
+ case LCD_BITS_PER_PIXEL_16_565:
+ case LCD_BITS_PER_PIXEL_12_444:
+
+ WidthInBytes = Width * 2;
+
+ for( LineCount = 0; LineCount < Height; LineCount++ ) {
+ // Update the start addresses of source & destination using 16bit pointer arithmetic
+ SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
+ DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+ // Copy the entire line Y from video ram to the temp buffer
+ CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+ // Update the line numbers
+ SourceLine += Step;
+ DestinationLine += Step;
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ default:
+ // Can't handle this case
+ DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ // break;
+
+ }
+
+ EXIT:
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+VideoCopyHorizontalOverlap (
+ IN UINTN BitsPerPixel,
+ IN volatile VOID *FrameBufferBase,
+ UINT32 HorizontalResolution,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ UINT32 *PixelBuffer32bit;
+ UINT32 *SourcePixel32bit;
+ UINT32 *DestinationPixel32bit;
+
+ UINT16 *PixelBuffer16bit;
+ UINT16 *SourcePixel16bit;
+ UINT16 *DestinationPixel16bit;
+
+ UINT32 SourcePixelY;
+ UINT32 DestinationPixelY;
+ UINTN SizeIn32Bits;
+ UINTN SizeIn16Bits;
+
+ switch (BitsPerPixel) {
+
+ case LCD_BITS_PER_PIXEL_24:
+ // Allocate a temporary buffer
+
+ PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
+
+ if (PixelBuffer32bit == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ SizeIn32Bits = Width * 4;
+
+ // Copy from the video ram (source region) to a temp buffer
+ for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
+ SourcePixelY < SourceY + Height;
+ SourcePixelY++, DestinationPixel32bit += Width)
+ {
+ // Update the start address of line Y (source)
+ SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+ // Copy the entire line Y from video ram to the temp buffer
+ CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+ }
+
+ // Copy from the temp buffer to the video ram (destination region)
+ for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
+ DestinationPixelY < DestinationY + Height;
+ DestinationPixelY++, SourcePixel32bit += Width)
+ {
+ // Update the start address of line Y (target)
+ DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
+
+ // Copy the entire line Y from the temp buffer to video ram
+ CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+ }
+
+ // Free up the allocated memory
+ FreePool((VOID *) PixelBuffer32bit);
+
+ break;
+
+
+ case LCD_BITS_PER_PIXEL_16_555:
+ case LCD_BITS_PER_PIXEL_16_565:
+ case LCD_BITS_PER_PIXEL_12_444:
+ // Allocate a temporary buffer
+ PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
+
+ if (PixelBuffer16bit == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
+
+ SizeIn16Bits = Width * 2;
+
+ for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
+ SourcePixelY < SourceY + Height;
+ SourcePixelY++, DestinationPixel16bit += Width)
+ {
+ // Calculate the source address:
+ SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+ // Copy the entire line Y from Video to the temp buffer
+ CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+ }
+
+ // Copy from the temp buffer into the destination area of the Video Memory
+
+ for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
+ DestinationPixelY < DestinationY + Height;
+ DestinationPixelY++, SourcePixel16bit += Width)
+ {
+ // Calculate the target address:
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
+
+ // Copy the entire line Y from the temp buffer to Video
+ CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+ }
+
+ // Free the allocated memory
+ FreePool((VOID *) PixelBuffer16bit);
+
+ break;
+
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ default:
+ // Can't handle this case
+ DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ // break;
+
+ }
+
+EXIT:
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoFill (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
+ )
+{
+ EFI_PIXEL_BITMASK* PixelInformation;
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ LCD_BPP BitsPerPixel;
+ VOID *FrameBufferBase;
+ VOID *DestinationAddr;
+ UINT16 *DestinationPixel16bit;
+ UINT16 Pixel16bit;
+ UINT32 DestinationPixelX;
+ UINT32 DestinationLine;
+ UINTN WidthInBytes;
+
+ Status = EFI_SUCCESS;
+ PixelInformation = &This->Mode->Info->PixelInformation;
+ FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+ HorizontalResolution = This->Mode->Info->HorizontalResolution;
+
+ LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+ switch (BitsPerPixel) {
+ case LCD_BITS_PER_PIXEL_24:
+ WidthInBytes = Width * 4;
+
+ // Copy the SourcePixel into every pixel inside the target rectangle
+ for (DestinationLine = DestinationY;
+ DestinationLine < DestinationY + Height;
+ DestinationLine++)
+ {
+ // Calculate the target address using 32bit pointer arithmetic:
+ DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+ // Fill the entire line
+ SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_555:
+ // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+ Pixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
+// | ( 0 & PixelInformation->ReservedMask )
+ );
+
+ // Copy the SourcePixel into every pixel inside the target rectangle
+ for (DestinationLine = DestinationY;
+ DestinationLine < DestinationY + Height;
+ DestinationLine++)
+ {
+ for (DestinationPixelX = DestinationX;
+ DestinationPixelX < DestinationX + Width;
+ DestinationPixelX++)
+ {
+ // Calculate the target address:
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ *DestinationPixel16bit = Pixel16bit;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_565:
+ // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+ Pixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
+ );
+
+ // Copy the SourcePixel into every pixel inside the target rectangle
+ for (DestinationLine = DestinationY;
+ DestinationLine < DestinationY + Height;
+ DestinationLine++)
+ {
+ for (DestinationPixelX = DestinationX;
+ DestinationPixelX < DestinationX + Width;
+ DestinationPixelX++)
+ {
+ // Calculate the target address:
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ *DestinationPixel16bit = Pixel16bit;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_12_444:
+ // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+ Pixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask )
+ );
+
+ // Copy the SourcePixel into every pixel inside the target rectangle
+ for (DestinationLine = DestinationY;
+ DestinationLine < DestinationY + Height;
+ DestinationLine++)
+ {
+ for (DestinationPixelX = DestinationX;
+ DestinationPixelX < DestinationX + Width;
+ DestinationPixelX++)
+ {
+ // Calculate the target address:
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ *DestinationPixel16bit = Pixel16bit;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ default:
+ // Can't handle this case
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToBltBuffer (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ LCD_BPP BitsPerPixel;
+ EFI_PIXEL_BITMASK *PixelInformation;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
+ VOID *FrameBufferBase;
+ VOID *SourceAddr;
+ VOID *DestinationAddr;
+ UINT16 *SourcePixel16bit;
+ UINT16 Pixel16bit;
+ UINT32 SourcePixelX;
+ UINT32 SourceLine;
+ UINT32 DestinationPixelX;
+ UINT32 DestinationLine;
+ UINT32 BltBufferHorizontalResolution;
+ UINTN WidthInBytes;
+
+ Status = EFI_SUCCESS;
+ PixelInformation = &This->Mode->Info->PixelInformation;
+ HorizontalResolution = This->Mode->Info->HorizontalResolution;
+ FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+ if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ // Delta is not zero and it is different from the width.
+ // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+ BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ } else {
+ BltBufferHorizontalResolution = Width;
+ }
+
+ LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+ switch (BitsPerPixel) {
+ case LCD_BITS_PER_PIXEL_24:
+ WidthInBytes = Width * 4;
+
+ // Access each line inside the Video Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++)
+ {
+ // Calculate the source and target addresses using 32bit pointer arithmetic:
+ SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
+ DestinationAddr = (VOID *)((UINT32 *)BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationX);
+
+ // Copy the entire line
+ CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_555:
+ // Access each pixel inside the Video Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++)
+ {
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+ EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+ // Snapshot the pixel from the video buffer once, to speed up the operation.
+ // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+ Pixel16bit = *SourcePixel16bit;
+
+ // Copy the pixel into the new target
+ EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 );
+ EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2);
+ EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
+ // EfiDestinationPixel->Reserved = (UINT8) 0;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_565:
+ // Access each pixel inside the Video Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++)
+ {
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+ EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+ // Snapshot the pixel from the video buffer once, to speed up the operation.
+ // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+ Pixel16bit = *SourcePixel16bit;
+
+ // Copy the pixel into the new target
+ // There is no info for the Reserved byte, so we set it to zero
+ EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 );
+ EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3);
+ EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
+ // EfiDestinationPixel->Reserved = (UINT8) 0;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_12_444:
+ // Access each pixel inside the Video Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++)
+ {
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+ EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+ // Snapshot the pixel from the video buffer once, to speed up the operation.
+ // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+ Pixel16bit = *SourcePixel16bit;
+
+ // Copy the pixel into the new target
+ EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 );
+ EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) );
+ EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 );
+ // EfiDestinationPixel->Reserved = (UINT8) 0;
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ default:
+ // Can't handle this case
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+BltBufferToVideo (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ LCD_BPP BitsPerPixel;
+ EFI_PIXEL_BITMASK *PixelInformation;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
+ VOID *FrameBufferBase;
+ VOID *SourceAddr;
+ VOID *DestinationAddr;
+ UINT16 *DestinationPixel16bit;
+ UINT32 SourcePixelX;
+ UINT32 SourceLine;
+ UINT32 DestinationPixelX;
+ UINT32 DestinationLine;
+ UINT32 BltBufferHorizontalResolution;
+ UINTN WidthInBytes;
+
+ Status = EFI_SUCCESS;
+ PixelInformation = &This->Mode->Info->PixelInformation;
+ HorizontalResolution = This->Mode->Info->HorizontalResolution;
+ FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+ if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ // Delta is not zero and it is different from the width.
+ // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+ BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ } else {
+ BltBufferHorizontalResolution = Width;
+ }
+
+ LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+ switch (BitsPerPixel) {
+ case LCD_BITS_PER_PIXEL_24:
+ WidthInBytes = Width * 4;
+
+ // Access each pixel inside the BltBuffer Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++)
+ {
+ // Calculate the source and target addresses using 32bit pointer arithmetic:
+ SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX );
+ DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+ // Copy the entire row Y
+ CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_555:
+ // Access each pixel inside the BltBuffer Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++) {
+
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ // Only the most significant bits will be copied across:
+ // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+ *DestinationPixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
+ // | ( 0 & PixelInformation->ReservedMask )
+ );
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_16_565:
+ // Access each pixel inside the BltBuffer Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++) {
+
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ // Only the most significant bits will be copied across:
+ // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits
+ // There is no room for the Reserved byte so we ignore that completely
+ *DestinationPixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
+ );
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_12_444:
+ // Access each pixel inside the BltBuffer Memory
+ for (SourceLine = SourceY, DestinationLine = DestinationY;
+ SourceLine < SourceY + Height;
+ SourceLine++, DestinationLine++) {
+
+ for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+ SourcePixelX < SourceX + Width;
+ SourcePixelX++, DestinationPixelX++)
+ {
+ // Calculate the source and target addresses:
+ EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+ DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+ // Copy the pixel into the new target
+ // Only the most significant bits will be copied across:
+ // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+ *DestinationPixel16bit = (UINT16) (
+ ( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask )
+ | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
+ | ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask )
+ // | ( 0 & PixelInformation->ReservedMask )
+ );
+ }
+ }
+ break;
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ default:
+ // Can't handle this case
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToVideo (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ LCD_BPP BitsPerPixel;
+ VOID *FrameBufferBase;
+
+ HorizontalResolution = This->Mode->Info->HorizontalResolution;
+ FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+ //
+ // BltVideo to BltVideo:
+ //
+ // Source is the Video Memory,
+ // Destination is the Video Memory
+
+ LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+ FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+ // The UEFI spec currently states:
+ // "There is no limitation on the overlapping of the source and destination rectangles"
+ // Therefore, we must be careful to avoid overwriting the source data
+ if( SourceY == DestinationY ) {
+ // Copying within the same height, e.g. horizontal shift
+ if( SourceX == DestinationX ) {
+ // Nothing to do
+ Status = EFI_SUCCESS;
+ } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
+ // There is overlap
+ Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+ } else {
+ // No overlap
+ Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+ }
+ } else {
+ // Copying from different heights
+ Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+ }
+
+ return Status;
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
+ *
+ * PRESUMES: 1 pixel = 4 bytes (32bits)
+ * ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ LCD_INSTANCE* Instance;
+
+ Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
+
+ // Setup the hardware if not already done
+ if (!mDisplayInitialized) {
+ Status = InitializeDisplay (Instance);
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+ }
+
+ HorizontalResolution = This->Mode->Info->HorizontalResolution;
+ VerticalResolution = This->Mode->Info->VerticalResolution;
+
+ DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
+ BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
+
+ // Check we have reasonable parameters
+ if (Width == 0 || Height == 0) {
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
+ ASSERT( BltBuffer != NULL);
+ }
+
+ /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }*/
+
+ // If we are reading data out of the video buffer, check that the source area is within the display limits
+ if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
+ if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
+ DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
+ DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
+ DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ }
+
+ // If we are writing data into the video buffer, that the destination area is within the display limits
+ if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
+ if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
+ DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
+ DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
+ DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ }
+
+ //
+ // Perform the Block Transfer Operation
+ //
+
+ switch (BltOperation) {
+ case EfiBltVideoFill:
+ Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case EfiBltVideoToBltBuffer:
+ Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case EfiBltBufferToVideo:
+ Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case EfiBltVideoToVideo:
+ Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case EfiGraphicsOutputBltOperationMax:
+ default:
+ DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+EXIT:
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
new file mode 100644
index 000000000..f1f104858
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
@@ -0,0 +1,394 @@
+/** @file
+ This file implements the Graphics Output protocol for Arm platforms
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+//
+// Global variables
+//
+
+BOOLEAN mDisplayInitialized = FALSE;
+
+LCD_INSTANCE mLcdTemplate = {
+ LCD_INSTANCE_SIGNATURE,
+ NULL, // Handle
+ { // ModeInfo
+ 0, // Version
+ 0, // HorizontalResolution
+ 0, // VerticalResolution
+ PixelBltOnly, // PixelFormat
+ { 0 }, // PixelInformation
+ 0, // PixelsPerScanLine
+ },
+ {
+ 0, // MaxMode;
+ 0, // Mode;
+ NULL, // Info;
+ 0, // SizeOfInfo;
+ 0, // FrameBufferBase;
+ 0 // FrameBufferSize;
+ },
+ { // Gop
+ LcdGraphicsQueryMode, // QueryMode
+ LcdGraphicsSetMode, // SetMode
+ LcdGraphicsBlt, // Blt
+ NULL // *Mode
+ },
+ { // DevicePath
+ {
+ {
+ HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ },
+ },
+ // Hardware Device Path for Lcd
+ EFI_CALLER_ID_GUID // Use the driver's GUID
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+ }
+ },
+ (EFI_EVENT)NULL // ExitBootServicesEvent
+};
+
+EFI_STATUS
+LcdInstanceContructor (
+ OUT LCD_INSTANCE** NewInstance
+ )
+{
+ LCD_INSTANCE* Instance;
+
+ Instance = AllocateCopyPool (sizeof (LCD_INSTANCE), &mLcdTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->Gop.Mode = &Instance->Mode;
+ Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
+ Instance->Mode.Info = &Instance->ModeInfo;
+
+ *NewInstance = Instance;
+ return EFI_SUCCESS;
+}
+
+//
+// Function Definitions
+//
+
+EFI_STATUS
+InitializeDisplay (
+ IN LCD_INSTANCE* Instance
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_PHYSICAL_ADDRESS VramBaseAddress;
+ UINTN VramSize;
+
+ Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Setup the LCD
+ Status = LcdInitialize (VramBaseAddress);
+ if (EFI_ERROR (Status)) {
+ goto EXIT_ERROR_LCD_SHUTDOWN;
+ }
+
+ Status = LcdPlatformInitializeDisplay (Instance->Handle);
+ if (EFI_ERROR (Status)) {
+ goto EXIT_ERROR_LCD_SHUTDOWN;
+ }
+
+ // Setup all the relevant mode information
+ Instance->Gop.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
+
+ // Set the flag before changing the mode, to avoid infinite loops
+ mDisplayInitialized = TRUE;
+
+ // All is ok, so don't deal with any errors
+ goto EXIT;
+
+EXIT_ERROR_LCD_SHUTDOWN:
+ DEBUG ((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
+
+ LcdShutdown ();
+
+EXIT:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsOutputDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ LCD_INSTANCE* Instance;
+
+ Status = LcdIdentify ();
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ Status = LcdInstanceContructor (&Instance);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ // Install the Graphics Output Protocol and the Device Path
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Instance->Gop,
+ &gEfiDevicePathProtocolGuid,
+ &Instance->DevicePath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
+ goto EXIT;
+ }
+
+ // Register for an ExitBootServicesEvent
+ // When ExitBootServices starts, this function will make sure that the
+ // graphics driver shuts down properly, i.e. it will free up all
+ // allocated memory and perform any necessary hardware re-configuration.
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_NOTIFY,
+ LcdGraphicsExitBootServicesEvent,
+ NULL,
+ &Instance->ExitBootServicesEvent
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
+ goto EXIT_ERROR_UNINSTALL_PROTOCOL;
+ }
+
+ // To get here, everything must be fine, so just exit
+ goto EXIT;
+
+EXIT_ERROR_UNINSTALL_PROTOCOL:
+ // The following function could return an error message,
+ // however, to get here something must have gone wrong already,
+ // so preserve the original error, i.e. don't change
+ // the Status variable, even it fails to uninstall the protocol.
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Instance->Gop, // Uninstall Graphics Output protocol
+ &gEfiDevicePathProtocolGuid,
+ &Instance->DevicePath, // Uninstall device path
+ NULL
+ );
+
+EXIT:
+ return Status;
+}
+
+/** This function should be called
+ on Event: ExitBootServices
+ to free up memory, stop the driver
+ and uninstall the protocols
+**/
+VOID
+LcdGraphicsExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // By default, this PCD is FALSE. But if a platform starts a predefined OS
+ // that does not use a framebuffer then we might want to disable the display
+ // controller to avoid to display corrupted information on the screen.
+ if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {
+ // Turn-off the Display controller
+ LcdShutdown ();
+ }
+}
+
+/** GraphicsOutput Protocol function, mapping to
+ EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
+**/
+EFI_STATUS
+EFIAPI
+LcdGraphicsQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ LCD_INSTANCE *Instance;
+
+ Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
+
+ // Setup the hardware if not already done
+ if (!mDisplayInitialized) {
+ Status = InitializeDisplay (Instance);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+
+ // Error checking
+ if ((This == NULL) ||
+ (Info == NULL) ||
+ (SizeOfInfo == NULL) ||
+ (ModeNumber >= This->Mode->MaxMode)) {
+ DEBUG ((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ if (*Info == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ Status = LcdPlatformQueryMode (ModeNumber, *Info);
+ if (EFI_ERROR (Status)) {
+ FreePool (*Info);
+ }
+
+EXIT:
+ return Status;
+}
+
+/** GraphicsOutput Protocol function, mapping to
+ EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
+**/
+EFI_STATUS
+EFIAPI
+LcdGraphicsSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;
+ LCD_INSTANCE* Instance;
+ LCD_BPP Bpp;
+
+ Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
+
+ // Setup the hardware if not already done
+ if (!mDisplayInitialized) {
+ Status = InitializeDisplay (Instance);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+
+ // Check if this mode is supported
+ if (ModeNumber >= This->Mode->MaxMode) {
+ DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber));
+ Status = EFI_UNSUPPORTED;
+ goto EXIT;
+ }
+
+ // Set the oscillator frequency to support the new mode
+ Status = LcdPlatformSetMode (ModeNumber);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Update the UEFI mode information
+ This->Mode->Mode = ModeNumber;
+ LcdPlatformQueryMode (ModeNumber, &Instance->ModeInfo);
+ Status = LcdPlatformGetBpp (ModeNumber, &Bpp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));
+ goto EXIT;
+ }
+ This->Mode->FrameBufferSize = Instance->ModeInfo.VerticalResolution
+ * Instance->ModeInfo.PixelsPerScanLine
+ * GetBytesPerPixel (Bpp);
+
+ // Set the hardware to the new mode
+ Status = LcdSetMode (ModeNumber);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // The UEFI spec requires that we now clear the visible portions of the
+ // output display to black.
+
+ // Set the fill colour to black
+ SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ // Fill the entire visible area with the same colour.
+ Status = This->Blt (
+ This,
+ &FillColour,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ 0,
+ This->Mode->Info->HorizontalResolution,
+ This->Mode->Info->VerticalResolution,
+ 0
+ );
+
+EXIT:
+ return Status;
+}
+
+UINTN
+GetBytesPerPixel (
+ IN LCD_BPP Bpp
+ )
+{
+ switch (Bpp) {
+ case LCD_BITS_PER_PIXEL_24:
+ return 4;
+
+ case LCD_BITS_PER_PIXEL_16_565:
+ case LCD_BITS_PER_PIXEL_16_555:
+ case LCD_BITS_PER_PIXEL_12_444:
+ return 2;
+
+ case LCD_BITS_PER_PIXEL_8:
+ case LCD_BITS_PER_PIXEL_4:
+ case LCD_BITS_PER_PIXEL_2:
+ case LCD_BITS_PER_PIXEL_1:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h
new file mode 100644
index 000000000..c49afd3b0
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h
@@ -0,0 +1,101 @@
+/** @file
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef LCD_GRAPHICS_OUTPUT_DXE_H_
+#define LCD_GRAPHICS_OUTPUT_DXE_H_
+
+#include <Base.h>
+
+#include <Library/DebugLib.h>
+#include <Library/LcdHwLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/DevicePath.h>
+
+//
+// Device structures
+//
+typedef struct {
+ VENDOR_DEVICE_PATH Guid;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} LCD_GRAPHICS_DEVICE_PATH;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE Mode;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL Gop;
+ LCD_GRAPHICS_DEVICE_PATH DevicePath;
+ EFI_EVENT ExitBootServicesEvent;
+} LCD_INSTANCE;
+
+#define LCD_INSTANCE_SIGNATURE SIGNATURE_32('l', 'c', 'd', '0')
+
+#define LCD_INSTANCE_FROM_GOP_THIS(a) CR (a, LCD_INSTANCE, Gop, LCD_INSTANCE_SIGNATURE)
+
+//
+// Function Prototypes
+//
+
+VOID
+LcdGraphicsExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+);
+
+UINTN
+GetBytesPerPixel (
+ IN LCD_BPP Bpp
+ );
+
+EFI_STATUS
+EFIAPI
+GraphicsOutputDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+);
+
+EFI_STATUS
+InitializeDisplay (
+ IN LCD_INSTANCE* Instance
+);
+
+#endif /* LCD_GRAPHICS_OUTPUT_DXE_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf
new file mode 100644
index 000000000..27453b265
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf
@@ -0,0 +1,49 @@
+#/** @file
+#
+# Component description file for LcdGraphicsOutputDxe module
+#
+# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = LcdGraphicsOutputDxe
+ FILE_GUID = 89464DAE-8DAA-41FE-A4C8-40D2175AF1E9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = LcdGraphicsOutputDxeInitialize
+
+[Sources.common]
+ LcdGraphicsOutputDxe.c
+ LcdGraphicsOutputBlt.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmPkg/ArmPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ ArmLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ LcdHwLib
+ LcdPlatformLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+
+[FeaturePcd]
+ gArmPlatformTokenSpaceGuid.PcdGopDisableOnExitBootServices
+
+[Depex]
+ TRUE
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
new file mode 100644
index 000000000..689d65223
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
@@ -0,0 +1,123 @@
+/** @file NorFlashBlockIoDxe.c
+
+ Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "NorFlashDxe.h"
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
+
+ return NorFlashReset (Instance);
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+ Media = This->Media;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+ if (!Media) {
+ Status = EFI_INVALID_PARAMETER;
+ } else if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ } else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+ if( !This->Media->MediaPresent ) {
+ Status = EFI_NO_MEDIA;
+ } else if( This->Media->MediaId != MediaId ) {
+ Status = EFI_MEDIA_CHANGED;
+ } else if( This->Media->ReadOnly ) {
+ Status = EFI_WRITE_PROTECTED;
+ } else {
+ Status = NorFlashWriteBlocks (Instance,Lba,BufferSizeInBytes,Buffer);
+ }
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ // No Flush required for the NOR Flash driver
+ // because cache operations are not permitted.
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
+
+ // Nothing to do so just return without error
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 000000000..d9e196cbf
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,1333 @@
+/** @file NorFlashDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+#include "NorFlashDxe.h"
+
+STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+UINT32 mNorFlashDeviceCount;
+
+NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
+ NOR_FLASH_SIGNATURE, // Signature
+ NULL, // Handle ... NEED TO BE FILLED
+
+ 0, // DeviceBaseAddress ... NEED TO BE FILLED
+ 0, // RegionBaseAddress ... NEED TO BE FILLED
+ 0, // Size ... NEED TO BE FILLED
+ 0, // StartLba
+
+ {
+ EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
+ NULL, // Media ... NEED TO BE FILLED
+ NorFlashBlockIoReset, // Reset;
+ NorFlashBlockIoReadBlocks, // ReadBlocks
+ NorFlashBlockIoWriteBlocks, // WriteBlocks
+ NorFlashBlockIoFlushBlocks // FlushBlocks
+ }, // BlockIoProtocol
+
+ {
+ 0, // MediaId ... NEED TO BE FILLED
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching;
+ 0, // BlockSize ... NEED TO BE FILLED
+ 4, // IoAlign
+ 0, // LastBlock ... NEED TO BE FILLED
+ 0, // LowestAlignedLba
+ 1, // LogicalBlocksPerPhysicalBlock
+ }, //Media;
+
+ {
+ EFI_DISK_IO_PROTOCOL_REVISION, // Revision
+ NorFlashDiskIoReadDisk, // ReadDisk
+ NorFlashDiskIoWriteDisk // WriteDisk
+ },
+
+ {
+ FvbGetAttributes, // GetAttributes
+ FvbSetAttributes, // SetAttributes
+ FvbGetPhysicalAddress, // GetPhysicalAddress
+ FvbGetBlockSize, // GetBlockSize
+ FvbRead, // Read
+ FvbWrite, // Write
+ FvbEraseBlocks, // EraseBlocks
+ NULL, //ParentHandle
+ }, // FvbProtoccol;
+ NULL, // ShadowBuffer
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
+ }
+ },
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GUID ... NEED TO BE FILLED
+ },
+ 0, // Index
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ } // DevicePath
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 Index,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE** NorFlashInstance
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE* Instance;
+
+ ASSERT(NorFlashInstance != NULL);
+
+ Instance = AllocateRuntimeCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->DeviceBaseAddress = NorFlashDeviceBase;
+ Instance->RegionBaseAddress = NorFlashRegionBase;
+ Instance->Size = NorFlashSize;
+
+ Instance->BlockIoProtocol.Media = &Instance->Media;
+ Instance->Media.MediaId = Index;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+
+ CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
+ Instance->DevicePath.Index = (UINT8)Index;
+
+ Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);;
+ if (Instance->ShadowBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (SupportFvb) {
+ NorFlashFvbInitialize (Instance);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+ } else {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ &gEfiDiskIoProtocolGuid, &Instance->DiskIoProtocol,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool (Instance);
+ return Status;
+ }
+ }
+
+ *NorFlashInstance = Instance;
+ return Status;
+}
+
+UINT32
+NorFlashReadStatusRegister (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN SR_Address
+ )
+{
+ // Prepare to read the status register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
+ return MmioRead32 (Instance->DeviceBaseAddress);
+}
+
+STATIC
+BOOLEAN
+NorFlashBlockIsLocked (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ UINT32 LockStatus;
+
+ // Send command for reading device id
+ SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+ // Read block lock status
+ LockStatus = MmioRead32 (CREATE_NOR_ADDRESS(BlockAddress, 2));
+
+ // Decode block lock status
+ LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
+
+ if ((LockStatus & 0x2) != 0) {
+ DEBUG((EFI_D_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
+ }
+
+ return ((LockStatus & 0x1) != 0);
+}
+
+STATIC
+EFI_STATUS
+NorFlashUnlockSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ UINT32 LockStatus;
+
+ // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
+ // and to protect shared data structures.
+
+ if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) == TRUE) {
+ do {
+ // Request a lock setup
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+ // Request an unlock
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+ // Send command for reading device id
+ SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+ // Read block lock status
+ LockStatus = MmioRead32 (CREATE_NOR_ADDRESS(BlockAddress, 2));
+
+ // Decode block lock status
+ LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
+ } while ((LockStatus & 0x1) == 1);
+ } else {
+ // Request a lock setup
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+ // Request an unlock
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+ // Wait until the status register gives us the all clear
+ do {
+ LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
+ } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+ }
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
+
+ DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (NorFlashBlockIsLocked (Instance, BlockAddress) == TRUE) {
+ Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
+ }
+
+ return Status;
+}
+
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+STATIC
+EFI_STATUS
+NorFlashEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ Status = EFI_SUCCESS;
+
+ // Request a block erase and then confirm it
+ SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
+ SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
+
+ // Wait until the status register gives us the all clear
+ do {
+ StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
+ DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_ERASE) {
+ DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ // The debug level message has been reduced because a device lock might happen. In this case we just retry it ...
+ DEBUG((EFI_D_INFO,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
+ Status = EFI_WRITE_PROTECTED;
+ }
+
+ if (EFI_ERROR(Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+/**
+ * This function unlock and erase an entire NOR Flash block.
+ **/
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_TPL OriginalTPL;
+
+ if (!EfiAtRuntime ()) {
+ // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ // This initialization is only to prevent the compiler to complain about the
+ // use of uninitialized variables
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Index = 0;
+ // The block erase might fail a first time (SW bug ?). Retry it ...
+ do {
+ // Unlock the block if we have to
+ Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
+ Index++;
+ } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+ if (Index == NOR_FLASH_ERASE_RETRY) {
+ DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index));
+ }
+
+ if (!EfiAtRuntime ()) {
+ // Interruptions can resume.
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+NorFlashWriteSingleWord (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN WordAddress,
+ IN UINT32 WriteData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ Status = EFI_SUCCESS;
+
+ // Request a write single word command
+ SEND_NOR_COMMAND(WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
+
+ // Store the word into NOR Flash;
+ MmioWrite32 (WordAddress, WriteData);
+
+ // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+ do {
+ // Prepare to read the status register
+ StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
+ // The chip is busy while the WRITE bit is not asserted
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+
+ // Perform a full status check:
+ // Mask the relevant bits of Status Register.
+ // Everything should be zero, if not, we have a problem
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n",WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_PROGRAM) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n",WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n",WordAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (!EFI_ERROR(Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+/*
+ * Writes data to the NOR Flash using the Buffered Programming method.
+ *
+ * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
+ * Therefore this function will only handle buffers up to 32 words or 128 bytes.
+ * To deal with larger buffers, call this function again.
+ *
+ * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
+ * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
+ *
+ * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
+ * then programming time is doubled and power consumption is increased.
+ * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
+ * i.e. the last 4 bits of the target start address must be zero: 0x......00
+ */
+EFI_STATUS
+NorFlashWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSizeInWords;
+ UINTN Count;
+ volatile UINT32 *Data;
+ UINTN WaitForBuffer;
+ BOOLEAN BufferAvailable;
+ UINT32 StatusRegister;
+
+ WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS;
+ BufferAvailable = FALSE;
+
+ // Check that the target address does not cross a 32-word boundary.
+ if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check there are some data to program
+ if (BufferSizeInBytes == 0) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
+ if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Check that the buffer size is a multiple of 32-bit words
+ if ((BufferSizeInBytes % 4) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Pre-programming conditions checked, now start the algorithm.
+
+ // Prepare the data destination address
+ Data = (UINT32 *)TargetAddress;
+
+ // Check the availability of the buffer
+ do {
+ // Issue the Buffered Program Setup command
+ SEND_NOR_COMMAND(TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
+
+ // Read back the status register bit#7 from the same address
+ if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
+ BufferAvailable = TRUE;
+ }
+
+ // Update the loop counter
+ WaitForBuffer--;
+
+ } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE));
+
+ // The buffer was not available for writing
+ if (WaitForBuffer == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // From now on we work in 32-bit words
+ BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
+
+ // Write the word count, which is (buffer_size_in_words - 1),
+ // because word count 0 means one word.
+ SEND_NOR_COMMAND(TargetAddress, 0, (BufferSizeInWords - 1));
+
+ // Write the data to the NOR Flash, advancing each address by 4 bytes
+ for(Count=0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
+ MmioWrite32 ((UINTN)Data, *Buffer);
+ }
+
+ // Issue the Buffered Program Confirm command, to start the programming operation
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
+
+ // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+ do {
+ StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
+ // The chip is busy while the WRITE bit is not asserted
+ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+
+ // Perform a full status check:
+ // Mask the relevant bits of Status Register.
+ // Everything should be zero, if not, we have a problem
+
+ Status = EFI_SUCCESS;
+
+ if (StatusRegister & P30_SR_BIT_VPP) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_PROGRAM) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
+ DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n",TargetAddress));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (!EFI_ERROR(Status)) {
+ // Clear the Status Register
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+EXIT:
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+NorFlashWriteFullBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINT32 *DataBuffer,
+ IN UINT32 BlockSizeInWords
+ )
+{
+ EFI_STATUS Status;
+ UINTN WordAddress;
+ UINT32 WordIndex;
+ UINTN BufferIndex;
+ UINTN BlockAddress;
+ UINTN BuffersInBlock;
+ UINTN RemainingWords;
+ EFI_TPL OriginalTPL;
+ UINTN Cnt;
+
+ Status = EFI_SUCCESS;
+
+ // Get the physical address of the block
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
+
+ // Start writing from the first address at the start of the block
+ WordAddress = BlockAddress;
+
+ if (!EfiAtRuntime ()) {
+ // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ // This initialization is only to prevent the compiler to complain about the
+ // use of uninitialized variables
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
+ goto EXIT;
+ }
+
+ // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
+
+ // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
+ if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
+
+ // First, break the entire block into buffer-sized chunks.
+ BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
+
+ // Then feed each buffer chunk to the NOR Flash
+ // If a buffer does not contain any data, don't write it.
+ for(BufferIndex=0;
+ BufferIndex < BuffersInBlock;
+ BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
+ ) {
+ // Check the buffer to see if it contains any data (not set all 1s).
+ for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
+ if (~DataBuffer[Cnt] != 0 ) {
+ // Some data found, write the buffer.
+ Status = NorFlashWriteBuffer (Instance, WordAddress, P30_MAX_BUFFER_SIZE_IN_BYTES,
+ DataBuffer);
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+ break;
+ }
+ }
+ }
+
+ // Finally, finish off any remaining words that are less than the maximum size of the buffer
+ RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
+
+ if(RemainingWords != 0) {
+ Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+ }
+
+ } else {
+ // For now, use the single word programming algorithm
+ // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
+ // i.e. which ends in the range 0x......01 - 0x......7F.
+ for(WordIndex=0; WordIndex<BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
+ Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+ }
+ }
+
+EXIT:
+ if (!EfiAtRuntime ()) {
+ // Interruptions can resume.
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
+ }
+ return Status;
+}
+
+
+EFI_STATUS
+NorFlashWriteBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ UINT32 *pWriteBuffer;
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_LBA CurrentBlock;
+ UINT32 BlockSizeInWords;
+ UINT32 NumBlocks;
+ UINT32 BlockCount;
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(Instance->Media.ReadOnly == TRUE) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ // We must have some bytes to read
+ DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
+ if(BufferSizeInBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
+
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+ DEBUG((EFI_D_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSizeInWords = Instance->Media.BlockSize / 4;
+
+ // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
+ // to a proper data type, so use *ReadBuffer
+ pWriteBuffer = (UINT32 *)Buffer;
+
+ CurrentBlock = Lba;
+ for (BlockCount=0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
+
+ DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
+
+ Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
+ return Status;
+}
+
+#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
+
+/**
+ Copy Length bytes from Source to Destination, using aligned accesses only.
+ Note that this implementation uses memcpy() semantics rather then memmove()
+ semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
+
+ @param DestinationBuffer The target of the copy request.
+ @param SourceBuffer The place to copy from.
+ @param Length The number of bytes to copy.
+
+ @return Destination
+
+**/
+STATIC
+VOID *
+AlignedCopyMem (
+ OUT VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ )
+{
+ UINT8 *Destination8;
+ CONST UINT8 *Source8;
+ UINT32 *Destination32;
+ CONST UINT32 *Source32;
+ UINT64 *Destination64;
+ CONST UINT64 *Source64;
+
+ if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 8) && Length >= 8) {
+ Destination64 = DestinationBuffer;
+ Source64 = SourceBuffer;
+ while (Length >= 8) {
+ *Destination64++ = *Source64++;
+ Length -= 8;
+ }
+
+ Destination8 = (UINT8 *)Destination64;
+ Source8 = (CONST UINT8 *)Source64;
+ } else if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 4) && Length >= 4) {
+ Destination32 = DestinationBuffer;
+ Source32 = SourceBuffer;
+ while (Length >= 4) {
+ *Destination32++ = *Source32++;
+ Length -= 4;
+ }
+
+ Destination8 = (UINT8 *)Destination32;
+ Source8 = (CONST UINT8 *)Source32;
+ } else {
+ Destination8 = DestinationBuffer;
+ Source8 = SourceBuffer;
+ }
+ while (Length-- != 0) {
+ *Destination8++ = *Source8++;
+ }
+ return DestinationBuffer;
+}
+
+EFI_STATUS
+NorFlashReadBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ UINT32 NumBlocks;
+ UINTN StartAddress;
+
+ DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
+ BufferSizeInBytes, Instance->Media.BlockSize, Instance->Media.LastBlock, Lba));
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Return if we have not any byte to read
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // The size of the buffer must be a multiple of the block size
+ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // All blocks must be within the device
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
+ DEBUG((EFI_D_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Put the device into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ // Readout the data
+ AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ UINTN StartAddress;
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Return if we have not any byte to read
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
+ DEBUG ((EFI_D_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the address to start reading from
+ StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Put the device into Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ // Readout the data
+ AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ Write a full or portion of a block. It must not span block boundaries; that is,
+ Offset + *NumBytes <= Instance->Media.BlockSize.
+*/
+EFI_STATUS
+NorFlashWriteSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS TempStatus;
+ UINT32 Tmp;
+ UINT32 TmpBuf;
+ UINT32 WordToWrite;
+ UINT32 Mask;
+ BOOLEAN DoErase;
+ UINTN BytesToWrite;
+ UINTN CurOffset;
+ UINTN WordAddr;
+ UINTN BlockSize;
+ UINTN BlockAddress;
+ UINTN PrevBlockAddress;
+
+ PrevBlockAddress = 0;
+
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
+ // It is in WriteDisabled state, return an error right away
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // The write must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ( ( Offset >= BlockSize ) ||
+ ( *NumBytes > BlockSize ) ||
+ ( (Offset + *NumBytes) > BlockSize ) ) {
+ DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to write
+ if (*NumBytes == 0) {
+ DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Pick 128bytes as a good start for word operations as opposed to erasing the
+ // block and writing the data regardless if an erase is really needed.
+ // It looks like most individual NV variable writes are smaller than 128bytes.
+ if (*NumBytes <= 128) {
+ // Check to see if we need to erase before programming the data into NOR.
+ // If the destination bits are only changing from 1s to 0s we can just write.
+ // After a block is erased all bits in the block is set to 1.
+ // If any byte requires us to erase we just give up and rewrite all of it.
+ DoErase = FALSE;
+ BytesToWrite = *NumBytes;
+ CurOffset = Offset;
+
+ while (BytesToWrite > 0) {
+ // Read full word from NOR, splice as required. A word is the smallest
+ // unit we can write.
+ TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof(Tmp), &Tmp);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Physical address of word in NOR to write.
+ WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress,
+ Lba, BlockSize);
+ // The word of data that is to be written.
+ TmpBuf = *((UINT32*)(Buffer + (*NumBytes - BytesToWrite)));
+
+ // First do word aligned chunks.
+ if ((CurOffset & 0x3) == 0) {
+ if (BytesToWrite >= 4) {
+ // Is the destination still in 'erased' state?
+ if (~Tmp != 0) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+ // Write this word to NOR
+ WordToWrite = TmpBuf;
+ CurOffset += sizeof(TmpBuf);
+ BytesToWrite -= sizeof(TmpBuf);
+ } else {
+ // BytesToWrite < 4. Do small writes and left-overs
+ Mask = ~((~0) << (BytesToWrite * 8));
+ // Mask out the bytes we want.
+ TmpBuf &= Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ CurOffset += BytesToWrite;
+ BytesToWrite = 0;
+ }
+ } else {
+ // Do multiple words, but starting unaligned.
+ if (BytesToWrite > (4 - (CurOffset & 0x3))) {
+ Mask = ((~0) << ((CurOffset & 0x3) * 8));
+ // Mask out the bytes we want.
+ TmpBuf &= Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ BytesToWrite -= (4 - (CurOffset & 0x3));
+ CurOffset += (4 - (CurOffset & 0x3));
+ } else {
+ // Unaligned and fits in one word.
+ Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
+ // Mask out the bytes we want.
+ TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
+ // Is the destination still in 'erased' state?
+ if ((Tmp & Mask) != Mask) {
+ // Check to see if we are only changing bits to zero.
+ if ((Tmp ^ TmpBuf) & TmpBuf) {
+ DoErase = TRUE;
+ break;
+ }
+ }
+ // Merge old and new data. Write merged word to NOR
+ WordToWrite = (Tmp & ~Mask) | TmpBuf;
+ CurOffset += BytesToWrite;
+ BytesToWrite = 0;
+ }
+ }
+
+ //
+ // Write the word to NOR.
+ //
+
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
+ if (BlockAddress != PrevBlockAddress) {
+ TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ PrevBlockAddress = BlockAddress;
+ }
+ TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ // Exit if we got here and could write all the data. Otherwise do the
+ // Erase-Write cycle.
+ if (!DoErase) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ // Check we did get some memory. Buffer is BlockSize.
+ if (Instance->ShadowBuffer == NULL) {
+ DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Read NOR Flash data into shadow buffer
+ TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Put the data at the appropriate location inside the buffer area
+ CopyMem ((VOID*)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+
+ // Write the modified buffer back to the NorFlash
+ TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/*
+ Although DiskIoDxe will automatically install the DiskIO protocol whenever
+ we install the BlockIO protocol, its implementation is sub-optimal as it reads
+ and writes entire blocks using the BlockIO protocol. In fact we can access
+ NOR flash with a finer granularity than that, so we can improve performance
+ by directly producing the DiskIO protocol.
+*/
+
+/**
+ Read BufferSize bytes from Offset into Buffer.
+
+ @param This Protocol instance pointer.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Offset The starting byte offset to read from
+ @param BufferSize Size of Buffer
+ @param Buffer Buffer containing read data
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoReadDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 DiskOffset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINT32 BlockSize;
+ UINT32 BlockOffset;
+ EFI_LBA Lba;
+
+ Instance = INSTANCE_FROM_DISKIO_THIS(This);
+
+ if (MediaId != Instance->Media.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ BlockSize = Instance->Media.BlockSize;
+ Lba = (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+ return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
+}
+
+/**
+ Writes a specified number of bytes to a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be written.
+ @param Offset The starting byte offset on the logical block I/O device to write.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
+ @param Buffer A pointer to the buffer containing the data to be written.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoWriteDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 DiskOffset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINT32 BlockSize;
+ UINT32 BlockOffset;
+ EFI_LBA Lba;
+ UINTN RemainingBytes;
+ UINTN WriteSize;
+ EFI_STATUS Status;
+
+ Instance = INSTANCE_FROM_DISKIO_THIS(This);
+
+ if (MediaId != Instance->Media.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ BlockSize = Instance->Media.BlockSize;
+ Lba = (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
+
+ RemainingBytes = BufferSize;
+
+ // Write either all the remaining bytes, or the number of bytes that bring
+ // us up to a block boundary, whichever is less.
+ // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
+ // block boundary (even if it is already on one).
+ WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
+
+ do {
+ if (WriteSize == BlockSize) {
+ // Write a full block
+ Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
+ } else {
+ // Write a partial block
+ Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ // Now continue writing either all the remaining bytes or single blocks.
+ RemainingBytes -= WriteSize;
+ Buffer = (UINT8 *) Buffer + WriteSize;
+ Lba++;
+ BlockOffset = 0;
+ WriteSize = MIN (RemainingBytes, BlockSize);
+ } while (RemainingBytes);
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashReset (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ return EFI_SUCCESS;
+}
+
+/**
+ 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
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+ // Convert BlockIo protocol
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
+
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
+
+ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->ShadowBuffer);
+ }
+ }
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ NOR_FLASH_DESCRIPTION* NorFlashDevices;
+ BOOLEAN ContainVariableStorage;
+
+ Status = NorFlashPlatformInitialization ();
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
+ return Status;
+ }
+
+ Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
+ return Status;
+ }
+
+ mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceCount);
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ // Check if this NOR Flash device contain the variable storage region
+ ContainVariableStorage =
+ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
+ (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <= NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+
+ Status = NorFlashCreateInstance (
+ NorFlashDevices[Index].DeviceBaseAddress,
+ NorFlashDevices[Index].RegionBaseAddress,
+ NorFlashDevices[Index].Size,
+ Index,
+ NorFlashDevices[Index].BlockSize,
+ ContainVariableStorage,
+ &mNorFlashInstances[Index]
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",Index));
+ }
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ NorFlashVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mNorFlashVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
new file mode 100644
index 000000000..a583e36c7
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
@@ -0,0 +1,358 @@
+/** @file NorFlashDxe.h
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __NOR_FLASH_DXE_H__
+#define __NOR_FLASH_DXE_H__
+
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NorFlashPlatformLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+// Device access macros
+// These are necessary because we use 2 x 16bit parts to make up 32bit data
+
+#define HIGH_16_BITS 0xFFFF0000
+#define LOW_16_BITS 0x0000FFFF
+#define LOW_8_BITS 0x000000FF
+
+#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
+
+#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
+#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
+
+// Each command must be sent simultaneously to both chips,
+// i.e. at the lower 16 bits AND at the higher 16 bits
+#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
+#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
+#define SEND_NOR_COMMAND(BaseAddr,Offset,Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+// Status Register Bits
+#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
+#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
+#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
+#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
+#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
+#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
+#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
+#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
+
+// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
+
+// On chip buffer size for buffered programming operations
+// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
+// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
+#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
+#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
+#define MAX_BUFFERED_PROG_ITERATIONS 10000000
+#define BOUNDARY_OF_32_WORDS 0x7F
+
+// CFI Addresses
+#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
+#define P30_CFI_ADDR_VENDOR_ID 0x13
+
+// CFI Data
+#define CFI_QRY 0x00595251
+
+// READ Commands
+#define P30_CMD_READ_DEVICE_ID 0x0090
+#define P30_CMD_READ_STATUS_REGISTER 0x0070
+#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
+#define P30_CMD_READ_ARRAY 0x00FF
+#define P30_CMD_READ_CFI_QUERY 0x0098
+
+// WRITE Commands
+#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
+#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
+#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
+#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
+#define P30_CMD_BEFP_SETUP 0x0080
+#define P30_CMD_BEFP_CONFIRM 0x00D0
+
+// ERASE Commands
+#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
+#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
+
+// SUSPEND Commands
+#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
+#define P30_CMD_SUSPEND_RESUME 0x00D0
+
+// BLOCK LOCKING / UNLOCKING Commands
+#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
+#define P30_CMD_LOCK_BLOCK 0x0001
+#define P30_CMD_UNLOCK_BLOCK 0x00D0
+#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
+
+// PROTECTION Commands
+#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
+
+// CONFIGURATION Commands
+#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
+#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
+
+#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE)
+
+typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT8 Index;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+#pragma pack ()
+
+struct _NOR_FLASH_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+
+ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
+ EFI_BLOCK_IO_MEDIA Media;
+ EFI_DISK_IO_PROTOCOL DiskIoProtocol;
+
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+ VOID* ShadowBuffer;
+
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+EFI_STATUS
+NorFlashReadCfiData (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN CFI_Offset,
+ IN UINT32 NumberOfBytes,
+ OUT UINT32 *Data
+ );
+
+EFI_STATUS
+NorFlashWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+);
+
+//
+// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk
+//
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoReadDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+//
+// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk
+//
+EFI_STATUS
+EFIAPI
+NorFlashDiskIoWriteDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+//
+// NorFlashFvbDxe.c
+//
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbRead(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbWrite(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ );
+
+//
+// NorFlashDxe.c
+//
+
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashWriteSingleBlock (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashWriteBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashReadBlocks (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashReset (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+#endif /* __NOR_FLASH_DXE_H__ */
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100644
index 000000000..a647c0168
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,67 @@
+#/** @file
+#
+# Component description file for NorFlashDxe module
+#
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmVeNorFlashDxe
+ FILE_GUID = 93E34C7E-B50E-11DF-9223-2443DFD72085
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NorFlashInitialise
+
+[Sources.common]
+ NorFlashDxe.h
+ NorFlashDxe.c
+ NorFlashFvbDxe.c
+ NorFlashBlockIoDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ IoLib
+ BaseLib
+ DebugLib
+ HobLib
+ NorFlashPlatformLib
+ UefiLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+ DxeServicesTableLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gEfiDiskIoProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+ gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
+
+[Depex]
+ gEfiCpuArchProtocolGuid
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
new file mode 100644
index 000000000..e248fdf6d
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
@@ -0,0 +1,800 @@
+/*++ @file NorFlashFvbDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ --*/
+
+#include <PiDxe.h>
+
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Guid/VariableFormat.h>
+#include <Guid/SystemNvDataGuid.h>
+#include <Guid/NvVarStoreFormatted.h>
+
+#include "NorFlashDxe.h"
+
+STATIC EFI_EVENT mFvbVirtualAddrChangeEvent;
+STATIC UINTN mFlashNvStorageVariableBase;
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ EFI_STATUS Status;
+ VOID* Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool(HeadersLength);
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase));
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase));
+
+ // Check if the size of the area is at least one block size
+ ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader,FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+
+ FreePool (Headers);
+ return Status;
+}
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress;
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((EFI_D_INFO, "%a: No Firmware Volume header present\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((EFI_D_INFO, "%a: Firmware Volume Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((EFI_D_INFO, "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__, Checksum));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
+ !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
+ DEBUG ((EFI_D_INFO, "%a: Variable Store Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((EFI_D_INFO, "%a: Variable Store Length does not match\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
+
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+
+ );
+
+ // Check if it is write protected
+ if (Instance->Media.ReadOnly != TRUE) {
+
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The SetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
+ that contains the desired firmware volume settings.
+ On successful return, it contains the new settings of
+ the firmware volume.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
+ as declared in the firmware volume header.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
+
+ ASSERT(Address != NULL);
+
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
+
+ if (Lba > Instance->Media.LastBlock) {
+ DEBUG ((EFI_D_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // This is easy because in this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN) Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be used
+ to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
+ in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS TempStatus;
+ UINTN BlockSize;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
+
+ TempStatus = EFI_SUCCESS;
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize)) {
+ DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ if (*NumBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Decide if we are doing full block reads or not.
+ if (*NumBytes % BlockSize != 0) {
+ TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
+ if (EFI_ERROR (TempStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ // Read NOR Flash data into shadow buffer
+ TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
+ if (EFI_ERROR (TempStatus)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
+
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to erase.
+
+ The list is terminated with an EFI_LBA_LIST_TERMINATOR.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
+ The firmware device may have been partially erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
+ not exist in the firmware volume.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ UINTN BlockAddress; // Physical address of Lba to erase
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ //Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // All blocks must be within range
+ DEBUG ((
+ DEBUG_BLKIO,
+ "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
+ Instance->StartLba + StartingLba,
+ (UINT64)NumOfLba,
+ Instance->Media.LastBlock
+ ));
+ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINTN);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0) {
+
+ // Get the physical address of Lba to erase
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
+ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR(Status)) {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+/**
+ 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
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+ UINTN RuntimeMmioRegionSize;
+
+ DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
+ ASSERT((Instance != NULL));
+
+ //
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+ //
+
+ // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
+ // even if we only use the small block region at the top of the NOR Flash.
+ // The reason is when the NOR Flash memory is set into program mode, the command
+ // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
+ RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ ASSERT_EFI_ERROR (Status);
+
+ mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
+
+ // Set the index of the first LBA for the FVB
+ Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // Determine if there is a valid header at the beginning of the NorFlash
+ Status = ValidateFvHeader (Instance);
+ }
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR(Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((EFI_D_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
+ DEBUG ((EFI_D_INFO, "%a: Installing a correct one for this volume.\n",
+ __FUNCTION__));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // The driver implementing the variable read service can now be dispatched;
+ // the varstore headers are in place.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gImageHandle,
+ &gEdkiiNvVarStoreFormattedGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
new file mode 100644
index 000000000..778bd6858
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c
@@ -0,0 +1,409 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+* Copyright (c) 2016, Linaro Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Protocol/EmbeddedGpio.h>
+
+#include "PL061Gpio.h"
+
+PLATFORM_GPIO_CONTROLLER *mPL061PlatformGpio;
+
+EFI_STATUS
+EFIAPI
+PL061Locate (
+ IN EMBEDDED_GPIO_PIN Gpio,
+ OUT UINTN *ControllerIndex,
+ OUT UINTN *ControllerOffset,
+ OUT UINTN *RegisterBase
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {
+ if ( (Gpio >= mPL061PlatformGpio->GpioController[Index].GpioIndex)
+ && (Gpio < mPL061PlatformGpio->GpioController[Index].GpioIndex
+ + mPL061PlatformGpio->GpioController[Index].InternalGpioCount)) {
+ *ControllerIndex = Index;
+ *ControllerOffset = Gpio % mPL061PlatformGpio->GpioController[Index].InternalGpioCount;
+ *RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;
+ return EFI_SUCCESS;
+ }
+ }
+ DEBUG ((EFI_D_ERROR, "%a, failed to locate gpio %d\n", __func__, Gpio));
+ return EFI_INVALID_PARAMETER;
+}
+
+//
+// The PL061 is a strange beast. The 8-bit data register is aliased across a
+// region 0x400 bytes in size, with bits [9:2] of the address operating as a
+// mask for both read and write operations:
+// For reads:
+// - All bits where their corresponding mask bit is 1 return the current
+// value of that bit in the GPIO_DATA register.
+// - All bits where their corresponding mask bit is 0 return 0.
+// For writes:
+// - All bits where their corresponding mask bit is 1 set the bit in the
+// GPIO_DATA register to the written value.
+// - All bits where their corresponding mask bit is 0 are left untouched
+// in the GPIO_DATA register.
+//
+// To keep this driver intelligible, PL061EffectiveAddress, PL061GetPins and
+// Pl061SetPins provide an internal abstraction from this interface.
+
+STATIC
+UINTN
+EFIAPI
+PL061EffectiveAddress (
+ IN UINTN Address,
+ IN UINTN Mask
+ )
+{
+ return ((Address + PL061_GPIO_DATA_REG_OFFSET) + (Mask << 2));
+}
+
+STATIC
+UINTN
+EFIAPI
+PL061GetPins (
+ IN UINTN Address,
+ IN UINTN Mask
+ )
+{
+ return MmioRead8 (PL061EffectiveAddress (Address, Mask));
+}
+
+STATIC
+VOID
+EFIAPI
+PL061SetPins (
+ IN UINTN Address,
+ IN UINTN Mask,
+ IN UINTN Value
+ )
+{
+ MmioWrite8 (PL061EffectiveAddress (Address, Mask), Value);
+}
+
+/**
+ Function implementations
+**/
+
+EFI_STATUS
+PL061Identify (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN RegisterBase;
+
+ if ( (mPL061PlatformGpio->GpioCount == 0)
+ || (mPL061PlatformGpio->GpioControllerCount == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {
+ if (mPL061PlatformGpio->GpioController[Index].InternalGpioCount != PL061_GPIO_PINS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;
+
+ // Check if this is a PrimeCell Peripheral
+ if ( (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID0) != 0x0D)
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID1) != 0xF0)
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID2) != 0x05)
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID3) != 0xB1)) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Check if this PrimeCell Peripheral is the PL061 GPIO
+ if ( (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID0) != 0x61)
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID1) != 0x10)
+ || ((MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)
+ || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID3) != 0x00)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+ Gets the state of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin to read
+ Value - state of the pin
+
+Returns:
+
+ EFI_SUCCESS - GPIO state returned in Value
+ EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
+**/
+EFI_STATUS
+EFIAPI
+Get (
+ IN EMBEDDED_GPIO *This,
+ IN EMBEDDED_GPIO_PIN Gpio,
+ OUT UINTN *Value
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index, Offset, RegisterBase;
+
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
+ ASSERT_EFI_ERROR (Status);
+
+ if (Value == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PL061GetPins (RegisterBase, GPIO_PIN_MASK(Offset))) {
+ *Value = 1;
+ } else {
+ *Value = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+ Sets the state of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin to modify
+ Mode - mode to set
+
+Returns:
+
+ EFI_SUCCESS - GPIO set as requested
+ EFI_UNSUPPORTED - Mode is not supported
+ EFI_INVALID_PARAMETER - Gpio pin is out of range
+**/
+EFI_STATUS
+EFIAPI
+Set (
+ IN EMBEDDED_GPIO *This,
+ IN EMBEDDED_GPIO_PIN Gpio,
+ IN EMBEDDED_GPIO_MODE Mode
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index, Offset, RegisterBase;
+
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Mode)
+ {
+ case GPIO_MODE_INPUT:
+ // Set the corresponding direction bit to LOW for input
+ MmioAnd8 (RegisterBase + PL061_GPIO_DIR_REG,
+ ~GPIO_PIN_MASK(Offset) & 0xFF);
+ break;
+
+ case GPIO_MODE_OUTPUT_0:
+ // Set the corresponding direction bit to HIGH for output
+ MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));
+ // Set the corresponding data bit to LOW for 0
+ PL061SetPins (RegisterBase, GPIO_PIN_MASK(Offset), 0);
+ break;
+
+ case GPIO_MODE_OUTPUT_1:
+ // Set the corresponding direction bit to HIGH for output
+ MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset));
+ // Set the corresponding data bit to HIGH for 1
+ PL061SetPins (RegisterBase, GPIO_PIN_MASK(Offset), 0xff);
+ break;
+
+ default:
+ // Other modes are not supported
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+ Gets the mode (function) of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin
+ Mode - pointer to output mode value
+
+Returns:
+
+ EFI_SUCCESS - mode value retrieved
+ EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
+
+**/
+EFI_STATUS
+EFIAPI
+GetMode (
+ IN EMBEDDED_GPIO *This,
+ IN EMBEDDED_GPIO_PIN Gpio,
+ OUT EMBEDDED_GPIO_MODE *Mode
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index, Offset, RegisterBase;
+
+ Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
+ ASSERT_EFI_ERROR (Status);
+
+ // Check for errors
+ if (Mode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if it is input or output
+ if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset)) {
+ // Pin set to output
+ if (PL061GetPins (RegisterBase, GPIO_PIN_MASK(Offset))) {
+ *Mode = GPIO_MODE_OUTPUT_1;
+ } else {
+ *Mode = GPIO_MODE_OUTPUT_0;
+ }
+ } else {
+ // Pin set to input
+ *Mode = GPIO_MODE_INPUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+Routine Description:
+
+ Sets the pull-up / pull-down resistor of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin
+ Direction - pull-up, pull-down, or none
+
+Returns:
+
+ EFI_UNSUPPORTED - Can not perform the requested operation
+
+**/
+EFI_STATUS
+EFIAPI
+SetPull (
+ IN EMBEDDED_GPIO *This,
+ IN EMBEDDED_GPIO_PIN Gpio,
+ IN EMBEDDED_GPIO_PULL Direction
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Protocol variable definition
+ **/
+EMBEDDED_GPIO gGpio = {
+ Get,
+ Set,
+ GetMode,
+ SetPull
+};
+
+/**
+ Initialize the state information for the Embedded Gpio protocol.
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+PL061InstallProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ GPIO_CONTROLLER *GpioController;
+
+ //
+ // Make sure the Gpio protocol has not been installed in the system yet.
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
+
+ Status = gBS->LocateProtocol (&gPlatformGpioProtocolGuid, NULL, (VOID **)&mPL061PlatformGpio);
+ if (EFI_ERROR (Status) && (Status == EFI_NOT_FOUND)) {
+ // Create the mPL061PlatformGpio
+ mPL061PlatformGpio = (PLATFORM_GPIO_CONTROLLER *)AllocateZeroPool (sizeof (PLATFORM_GPIO_CONTROLLER) + sizeof (GPIO_CONTROLLER));
+ if (mPL061PlatformGpio == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to allocate PLATFORM_GPIO_CONTROLLER\n", __func__));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ mPL061PlatformGpio->GpioCount = PL061_GPIO_PINS;
+ mPL061PlatformGpio->GpioControllerCount = 1;
+ mPL061PlatformGpio->GpioController = (GPIO_CONTROLLER *)((UINTN) mPL061PlatformGpio + sizeof (PLATFORM_GPIO_CONTROLLER));
+
+ GpioController = mPL061PlatformGpio->GpioController;
+ GpioController->RegisterBase = (UINTN) PcdGet32 (PcdPL061GpioBase);
+ GpioController->GpioIndex = 0;
+ GpioController->InternalGpioCount = PL061_GPIO_PINS;
+ }
+
+ Status = PL061Identify();
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Install the Embedded GPIO Protocol onto a new handle
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEmbeddedGpioProtocolGuid, &gGpio,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.h b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.h
new file mode 100644
index 000000000..92ddf64b9
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.h
@@ -0,0 +1,43 @@
+/** @file
+*
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#ifndef __PL061_GPIO_H__
+#define __PL061_GPIO_H__
+
+#include <Protocol/EmbeddedGpio.h>
+
+// PL061 GPIO Registers
+#define PL061_GPIO_DATA_REG_OFFSET ((UINTN) 0x000)
+#define PL061_GPIO_DATA_REG 0x000
+#define PL061_GPIO_DIR_REG 0x400
+#define PL061_GPIO_IS_REG 0x404
+#define PL061_GPIO_IBE_REG 0x408
+#define PL061_GPIO_IEV_REG 0x40C
+#define PL061_GPIO_IE_REG 0x410
+#define PL061_GPIO_RIS_REG 0x414
+#define PL061_GPIO_MIS_REG 0x410
+#define PL061_GPIO_IC_REG 0x41C
+#define PL061_GPIO_AFSEL_REG 0x420
+
+#define PL061_GPIO_PERIPH_ID0 0xFE0
+#define PL061_GPIO_PERIPH_ID1 0xFE4
+#define PL061_GPIO_PERIPH_ID2 0xFE8
+#define PL061_GPIO_PERIPH_ID3 0xFEC
+
+#define PL061_GPIO_PCELL_ID0 0xFF0
+#define PL061_GPIO_PCELL_ID1 0xFF4
+#define PL061_GPIO_PCELL_ID2 0xFF8
+#define PL061_GPIO_PCELL_ID3 0xFFC
+
+#define PL061_GPIO_PINS 8
+
+// All bits low except one bit high, native bit length
+#define GPIO_PIN_MASK(Pin) (1UL << ((UINTN)(Pin)))
+
+#endif // __PL061_GPIO_H__
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
new file mode 100644
index 000000000..132f09ce2
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
@@ -0,0 +1,45 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL061GpioDxe
+ FILE_GUID = 5c1997d7-8d45-4f21-af3c-2206b8ed8bec
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PL061InstallProtocol
+[Sources.common]
+ PL061Gpio.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Pcd]
+ gArmPlatformTokenSpaceGuid.PcdPL061GpioBase
+
+[Protocols]
+ gEmbeddedGpioProtocolGuid
+ gPlatformGpioProtocolGuid
+
+[Depex]
+ TRUE
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.c b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.c
new file mode 100644
index 000000000..5029d21e0
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.c
@@ -0,0 +1,431 @@
+/** @file
+*
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+* Copyright (c) 2018, Linaro Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Protocol/HardwareInterrupt.h>
+#include <Protocol/WatchdogTimer.h>
+
+#include "SP805Watchdog.h"
+
+STATIC EFI_EVENT mEfiExitBootServicesEvent;
+STATIC EFI_HARDWARE_INTERRUPT_PROTOCOL *mInterrupt;
+STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify;
+STATIC UINT32 mTimerPeriod;
+
+/**
+ Make sure the SP805 registers are unlocked for writing.
+
+ Note: The SP805 Watchdog Timer supports locking of its registers,
+ i.e. it inhibits all writes to avoid rogue software accidentally
+ corrupting their contents.
+**/
+STATIC
+VOID
+SP805Unlock (
+ VOID
+ )
+{
+ if (MmioRead32 (SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_LOCKED) {
+ MmioWrite32 (SP805_WDOG_LOCK_REG, SP805_WDOG_SPECIAL_UNLOCK_CODE);
+ }
+}
+
+/**
+ Make sure the SP805 registers are locked and can not be overwritten.
+
+ Note: The SP805 Watchdog Timer supports locking of its registers,
+ i.e. it inhibits all writes to avoid rogue software accidentally
+ corrupting their contents.
+**/
+STATIC
+VOID
+SP805Lock (
+ VOID
+ )
+{
+ if (MmioRead32 (SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_UNLOCKED) {
+ // To lock it, just write in any number (except the special unlock code).
+ MmioWrite32 (SP805_WDOG_LOCK_REG, SP805_WDOG_LOCK_IS_LOCKED);
+ }
+}
+
+STATIC
+VOID
+EFIAPI
+SP805InterruptHandler (
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SP805Unlock ();
+ MmioWrite32 (SP805_WDOG_INT_CLR_REG, 0); // write of any value clears the irq
+ SP805Lock ();
+
+ mInterrupt->EndOfInterrupt (mInterrupt, Source);
+
+ //
+ // The notify function should be called with the elapsed number of ticks
+ // since the watchdog was armed, which should exceed the timer period.
+ // We don't actually know the elapsed number of ticks, so let's return
+ // the timer period plus 1.
+ //
+ if (mWatchdogNotify != NULL) {
+ mWatchdogNotify (mTimerPeriod + 1);
+ }
+
+ gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, 0, NULL);
+}
+
+/**
+ Stop the SP805 watchdog timer from counting down by disabling interrupts.
+**/
+STATIC
+VOID
+SP805Stop (
+ VOID
+ )
+{
+ // Disable interrupts
+ if ((MmioRead32 (SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) != 0) {
+ MmioAnd32 (SP805_WDOG_CONTROL_REG, ~SP805_WDOG_CTRL_INTEN);
+ }
+}
+
+/**
+ Starts the SP805 counting down by enabling interrupts.
+ The count down will start from the value stored in the Load register,
+ not from the value where it was previously stopped.
+**/
+STATIC
+VOID
+SP805Start (
+ VOID
+ )
+{
+ // Enable interrupts
+ if ((MmioRead32 (SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) == 0) {
+ MmioOr32 (SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_INTEN);
+ }
+}
+
+/**
+ On exiting boot services we must make sure the SP805 Watchdog Timer
+ is stopped.
+**/
+STATIC
+VOID
+EFIAPI
+ExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ SP805Unlock ();
+ SP805Stop ();
+ SP805Lock ();
+}
+
+/**
+ This function registers the handler NotifyFunction so it is called every time
+ the watchdog timer expires. It also passes the amount of time since the last
+ handler call to the NotifyFunction.
+ If NotifyFunction is not NULL and a handler is not already registered,
+ then the new handler is registered and EFI_SUCCESS is returned.
+ If NotifyFunction is NULL, and a handler is already registered,
+ then that handler is unregistered.
+ If an attempt is made to register a handler when a handler is already registered,
+ then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+
+ @retval EFI_SUCCESS The watchdog timer handler was registered.
+ @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
+ previously registered.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SP805RegisterHandler (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
+ )
+{
+ if (mWatchdogNotify == NULL && NotifyFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mWatchdogNotify != NULL && NotifyFunction != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mWatchdogNotify = NotifyFunction;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SP805SetTimerPeriod (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod // In 100ns units
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Ticks64bit;
+
+ SP805Unlock ();
+
+ Status = EFI_SUCCESS;
+
+ if (TimerPeriod == 0) {
+ // This is a watchdog stop request
+ SP805Stop ();
+ } else {
+ // Calculate the Watchdog ticks required for a delay of (TimerTicks * 100) nanoseconds
+ // The SP805 will count down to zero and generate an interrupt.
+ //
+ // WatchdogTicks = ((TimerPeriod * 100 * SP805_CLOCK_FREQUENCY) / 1GHz);
+ //
+ // i.e.:
+ //
+ // WatchdogTicks = (TimerPeriod * SP805_CLOCK_FREQUENCY) / 10 MHz ;
+
+ Ticks64bit = MultU64x32 (TimerPeriod, PcdGet32 (PcdSP805WatchdogClockFrequencyInHz));
+ Ticks64bit = DivU64x32 (Ticks64bit, 10 * 1000 * 1000);
+
+ // The registers in the SP805 are only 32 bits
+ if (Ticks64bit > MAX_UINT32) {
+ // We could load the watchdog with the maximum supported value but
+ // if a smaller value was requested, this could have the watchdog
+ // triggering before it was intended.
+ // Better generate an error to let the caller know.
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Update the watchdog with a 32-bit value.
+ MmioWrite32 (SP805_WDOG_LOAD_REG, (UINT32)Ticks64bit);
+
+ // Start the watchdog
+ SP805Start ();
+ }
+
+ mTimerPeriod = TimerPeriod;
+
+EXIT:
+ // Ensure the watchdog is locked before exiting.
+ SP805Lock ();
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SP805GetTimerPeriod (
+ IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ if (TimerPeriod == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerPeriod = mTimerPeriod;
+ return EFI_SUCCESS;
+}
+
+/**
+ Interface structure for the Watchdog Architectural Protocol.
+
+ @par Protocol Description:
+ This protocol provides a service to set the amount of time to wait
+ before firing the watchdog timer, and it also provides a service to
+ register a handler that is invoked when the watchdog timer fires.
+
+ @par When the watchdog timer fires, control will be passed to a handler
+ if one has been registered. If no handler has been registered,
+ or the registered handler returns, then the system will be
+ reset by calling the Runtime Service ResetSystem().
+
+ @param RegisterHandler
+ Registers a handler that will be called each time the
+ watchdogtimer interrupt fires. TimerPeriod defines the minimum
+ time between timer interrupts, so TimerPeriod will also
+ be the minimum time between calls to the registered
+ handler.
+ NOTE: If the watchdog resets the system in hardware, then
+ this function will not have any chance of executing.
+
+ @param SetTimerPeriod
+ Sets the period of the timer interrupt in 100 nS units.
+ This function is optional, and may return EFI_UNSUPPORTED.
+ If this function is supported, then the timer period will
+ be rounded up to the nearest supported timer period.
+
+ @param GetTimerPeriod
+ Retrieves the period of the timer interrupt in 100 nS units.
+
+**/
+STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = {
+ SP805RegisterHandler,
+ SP805SetTimerPeriod,
+ SP805GetTimerPeriod
+};
+
+/**
+ Initialize the state information for the Watchdog Timer Architectural Protocol.
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+SP805Initialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ // Find the interrupt controller protocol. ASSERT if not found.
+ Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL,
+ (VOID **)&mInterrupt);
+ ASSERT_EFI_ERROR (Status);
+
+ // Unlock access to the SP805 registers
+ SP805Unlock ();
+
+ // Stop the watchdog from triggering unexpectedly
+ SP805Stop ();
+
+ // Set the watchdog to reset the board when triggered
+ // This is a last resort in case the interrupt handler fails
+ if ((MmioRead32 (SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_RESEN) == 0) {
+ MmioOr32 (SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_RESEN);
+ }
+
+ // Clear any pending interrupts
+ MmioWrite32 (SP805_WDOG_INT_CLR_REG, 0); // write of any value clears the irq
+
+ // Prohibit any rogue access to SP805 registers
+ SP805Lock ();
+
+ if (PcdGet32 (PcdSP805WatchdogInterrupt) > 0) {
+ Status = mInterrupt->RegisterInterruptSource (mInterrupt,
+ PcdGet32 (PcdSP805WatchdogInterrupt),
+ SP805InterruptHandler);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: failed to register watchdog interrupt - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+ } else {
+ DEBUG ((DEBUG_WARN, "%a: no interrupt specified, running in RESET mode only\n",
+ __FUNCTION__));
+ }
+
+ //
+ // Make sure the Watchdog Timer Architectural Protocol has not been installed in the system yet.
+ // This will avoid conflicts with the universal watchdog
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);
+
+ // Register for an ExitBootServicesEvent
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY,
+ ExitBootServicesEvent, NULL, &mEfiExitBootServicesEvent);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ // Install the Timer Architectural Protocol onto a new handle
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiWatchdogTimerArchProtocolGuid, &mWatchdogTimer,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+EXIT:
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.h b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.h
new file mode 100644
index 000000000..df711400e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.h
@@ -0,0 +1,42 @@
+/** @file
+*
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#ifndef __SP805_WATCHDOG_H__
+#define __SP805_WATCHDOG_H__
+
+// SP805 Watchdog Registers
+#define SP805_WDOG_LOAD_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x000)
+#define SP805_WDOG_CURRENT_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x004)
+#define SP805_WDOG_CONTROL_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x008)
+#define SP805_WDOG_INT_CLR_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x00C)
+#define SP805_WDOG_RAW_INT_STS_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x010)
+#define SP805_WDOG_MSK_INT_STS_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0x014)
+#define SP805_WDOG_LOCK_REG ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xC00)
+
+#define SP805_WDOG_PERIPH_ID0 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFE0)
+#define SP805_WDOG_PERIPH_ID1 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFE4)
+#define SP805_WDOG_PERIPH_ID2 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFE8)
+#define SP805_WDOG_PERIPH_ID3 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFEC)
+
+#define SP805_WDOG_PCELL_ID0 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFF0)
+#define SP805_WDOG_PCELL_ID1 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFF4)
+#define SP805_WDOG_PCELL_ID2 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFF8)
+#define SP805_WDOG_PCELL_ID3 ((UINT32)PcdGet32 (PcdSP805WatchdogBase) + 0xFFC)
+
+// Timer control register bit definitions
+#define SP805_WDOG_CTRL_INTEN BIT0
+#define SP805_WDOG_CTRL_RESEN BIT1
+#define SP805_WDOG_RAW_INT_STS_WDOGRIS BIT0
+#define SP805_WDOG_MSK_INT_STS_WDOGMIS BIT0
+
+#define SP805_WDOG_LOCK_IS_UNLOCKED 0x00000000
+#define SP805_WDOG_LOCK_IS_LOCKED 0x00000001
+#define SP805_WDOG_SPECIAL_UNLOCK_CODE 0x1ACCE551
+
+#endif // __SP805_WATCHDOG_H__
diff --git a/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
new file mode 100644
index 000000000..048f6697e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
@@ -0,0 +1,45 @@
+/** @file
+*
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+* Copyright (c) 2018, Linaro Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SP805WatchdogDxe
+ FILE_GUID = ebd705fb-fa92-46a7-b32b-7f566d944614
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SP805Initialize
+
+[Sources.common]
+ SP805Watchdog.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Pcd]
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogClockFrequencyInHz
+ gArmPlatformTokenSpaceGuid.PcdSP805WatchdogInterrupt
+
+[Protocols]
+ gHardwareInterruptProtocolGuid ## ALWAYS_CONSUMES
+ gEfiWatchdogTimerArchProtocolGuid ## ALWAYS_PRODUCES
+
+[Depex]
+ gHardwareInterruptProtocolGuid
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/ArmPlatformLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/ArmPlatformLib.h
new file mode 100644
index 000000000..225183af2
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/ArmPlatformLib.h
@@ -0,0 +1,139 @@
+/** @file
+*
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef _ARMPLATFORMLIB_H_
+#define _ARMPLATFORMLIB_H_
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+//
+// The protocols, PPI and GUID definitions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+
+#include <Library/ArmLib.h>
+
+/**
+ Return the core position from the value of its MpId register
+
+ This function returns the core position from the position 0 in the processor.
+ This function might be called from assembler before any stack is set.
+
+ @return Return the core position
+
+**/
+UINTN
+ArmPlatformGetCorePosition (
+ IN UINTN MpId
+ );
+
+/**
+ Return a non-zero value if the callee is the primary core
+
+ This function returns a non-zero value if the callee is the primary core.
+ The primary core is the core responsible to initialize the hardware and run UEFI.
+ This function might be called from assembler before any stack is set.
+
+ @return Return a non-zero value if the callee is the primary core.
+
+**/
+UINTN
+ArmPlatformIsPrimaryCore (
+ IN UINTN MpId
+ );
+
+/**
+ Return the MpId of the primary core
+
+ This function returns the MpId of the primary core.
+ This function might be called from assembler before any stack is set.
+
+ @return Return the MpId of the primary core
+
+**/
+UINTN
+ArmPlatformGetPrimaryCoreMpId (
+ 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
+ );
+
+/**
+ First platform specific function to be called in the PEI phase
+
+ This function is actually the first function called by the PrePi
+ or PrePeiCore modules. It allows to retrieve arguments passed to
+ the UEFI firmware through the CPU registers.
+
+ This function might be written into assembler as no stack are set
+ when the function is invoked.
+
+**/
+VOID
+ArmPlatformPeiBootAction (
+ VOID
+ );
+
+/**
+ Initialize controllers that must setup in the normal world
+
+ This function is called by the ArmPlatformPkg/PrePi or ArmPlatformPkg/PlatformPei
+ in the PEI phase.
+
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ );
+
+/**
+ 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 (
+ OUT ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+ );
+
+/**
+ Return the Platform specific PPIs
+
+ This function exposes the Platform Specific PPIs. They can be used by any PrePi modules or passed
+ to the PeiCore by PrePeiCore.
+
+ @param[out] PpiListSize Size in Bytes of the Platform PPI List
+ @param[out] PpiList Platform PPI List
+
+**/
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ );
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h
new file mode 100644
index 000000000..6b4c4cd3f
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h
@@ -0,0 +1,62 @@
+/** @file LcdHwLib.h
+
+ This file contains interface functions for LcdHwLib of ArmPlatformPkg
+
+ Copyright (c) 2017, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef LCD_HW_LIB_H_
+#define LCD_HW_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Check for presence of display
+
+ @retval EFI_SUCCESS Platform implements display.
+ @retval EFI_NOT_FOUND Display not found on the platform.
+
+**/
+EFI_STATUS
+LcdIdentify (
+ VOID
+ );
+
+/**
+ Initialize display.
+
+ @param FrameBaseAddress Address of the frame buffer.
+ @retval EFI_SUCCESS Display initialization success.
+ @retval !(EFI_SUCCESS) Display initialization failure.
+
+**/
+EFI_STATUS
+LcdInitialize (
+ EFI_PHYSICAL_ADDRESS FrameBaseAddress
+ );
+
+/**
+ Set requested mode of the display.
+
+ @param ModeNumber Display mode number.
+ @retval EFI_SUCCESS Display set mode success.
+ @retval EFI_DEVICE_ERROR If mode not found/supported.
+
+**/
+EFI_STATUS
+LcdSetMode (
+ IN UINT32 ModeNumber
+ );
+
+/**
+ De-initializes the display.
+**/
+VOID
+LcdShutdown (
+ VOID
+ );
+
+#endif /* LCD_HW_LIB_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/LcdPlatformLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/LcdPlatformLib.h
new file mode 100644
index 000000000..ba2448707
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/LcdPlatformLib.h
@@ -0,0 +1,326 @@
+/** @file
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef LCD_PLATFORM_LIB_H_
+#define LCD_PLATFORM_LIB_H_
+
+#include <Protocol/GraphicsOutput.h>
+
+#define LCD_VRAM_SIZE SIZE_8MB
+
+// Modes definitions
+#define VGA 0
+#define SVGA 1
+#define XGA 2
+#define SXGA 3
+#define WSXGA 4
+#define UXGA 5
+#define HD 6
+#define WVGA 7
+#define QHD 8
+#define WSVGA 9
+#define HD720 10
+#define WXGA 11
+
+// VGA Mode: 640 x 480
+#define VGA_H_RES_PIXELS 640
+#define VGA_V_RES_PIXELS 480
+#define VGA_OSC_FREQUENCY 23750000 /* 0x016A6570 */
+
+#define VGA_H_SYNC ( 80 - 1)
+#define VGA_H_FRONT_PORCH ( 16 - 1)
+#define VGA_H_BACK_PORCH ( 64 - 1)
+
+#define VGA_V_SYNC ( 4 - 1)
+#define VGA_V_FRONT_PORCH ( 3 - 1)
+#define VGA_V_BACK_PORCH ( 13 - 1)
+
+// SVGA Mode: 800 x 600
+#define SVGA_H_RES_PIXELS 800
+#define SVGA_V_RES_PIXELS 600
+#define SVGA_OSC_FREQUENCY 38250000 /* 0x0247A610 */
+
+#define SVGA_H_SYNC ( 80 - 1)
+#define SVGA_H_FRONT_PORCH ( 32 - 1)
+#define SVGA_H_BACK_PORCH (112 - 1)
+
+#define SVGA_V_SYNC ( 4 - 1)
+#define SVGA_V_FRONT_PORCH ( 3 - 1)
+#define SVGA_V_BACK_PORCH ( 17 - 1)
+
+// XGA Mode: 1024 x 768
+#define XGA_H_RES_PIXELS 1024
+#define XGA_V_RES_PIXELS 768
+#define XGA_OSC_FREQUENCY 63500000 /* 0x03C8EEE0 */
+
+#define XGA_H_SYNC (104 - 1)
+#define XGA_H_FRONT_PORCH ( 48 - 1)
+#define XGA_H_BACK_PORCH (152 - 1)
+
+#define XGA_V_SYNC ( 4 - 1)
+#define XGA_V_FRONT_PORCH ( 3 - 1)
+#define XGA_V_BACK_PORCH ( 23 - 1)
+
+// SXGA Mode: 1280 x 1024
+#define SXGA_H_RES_PIXELS 1280
+#define SXGA_V_RES_PIXELS 1024
+#define SXGA_OSC_FREQUENCY 109000000 /* 0x067F3540 */
+
+#define SXGA_H_SYNC (136 - 1)
+#define SXGA_H_FRONT_PORCH ( 80 - 1)
+#define SXGA_H_BACK_PORCH (216 - 1)
+
+#define SXGA_V_SYNC ( 7 - 1)
+#define SXGA_V_FRONT_PORCH ( 3 - 1)
+#define SXGA_V_BACK_PORCH ( 29 - 1)
+
+// WSXGA+ Mode: 1680 x 1050
+#define WSXGA_H_RES_PIXELS 1680
+#define WSXGA_V_RES_PIXELS 1050
+#define WSXGA_OSC_FREQUENCY 147000000 /* 0x08C30AC0 */
+
+#define WSXGA_H_SYNC (170 - 1)
+#define WSXGA_H_FRONT_PORCH (104 - 1)
+#define WSXGA_H_BACK_PORCH (274 - 1)
+
+#define WSXGA_V_SYNC ( 5 - 1)
+#define WSXGA_V_FRONT_PORCH ( 4 - 1)
+#define WSXGA_V_BACK_PORCH ( 41 - 1)
+
+// UXGA Mode: 1600 x 1200
+#define UXGA_H_RES_PIXELS 1600
+#define UXGA_V_RES_PIXELS 1200
+#define UXGA_OSC_FREQUENCY 161000000 /* 0x0998AA40 */
+
+#define UXGA_H_SYNC (168 - 1)
+#define UXGA_H_FRONT_PORCH (112 - 1)
+#define UXGA_H_BACK_PORCH (280 - 1)
+
+#define UXGA_V_SYNC ( 4 - 1)
+#define UXGA_V_FRONT_PORCH ( 3 - 1)
+#define UXGA_V_BACK_PORCH ( 38 - 1)
+
+// HD Mode: 1920 x 1080
+#define HD_H_RES_PIXELS 1920
+#define HD_V_RES_PIXELS 1080
+#define HD_OSC_FREQUENCY 165000000 /* 0x09D5B340 */
+
+#define HD_H_SYNC ( 79 - 1)
+#define HD_H_FRONT_PORCH (128 - 1)
+#define HD_H_BACK_PORCH (328 - 1)
+
+#define HD_V_SYNC ( 5 - 1)
+#define HD_V_FRONT_PORCH ( 3 - 1)
+#define HD_V_BACK_PORCH ( 32 - 1)
+
+// WVGA Mode: 800 x 480
+#define WVGA_H_RES_PIXELS 800
+#define WVGA_V_RES_PIXELS 480
+#define WVGA_OSC_FREQUENCY 29500000 /* 0x01C22260 */
+#define WVGA_H_SYNC ( 72 - 1)
+#define WVGA_H_FRONT_PORCH ( 24 - 1)
+#define WVGA_H_BACK_PORCH ( 96 - 1)
+#define WVGA_V_SYNC ( 7 - 1)
+#define WVGA_V_FRONT_PORCH ( 3 - 1)
+#define WVGA_V_BACK_PORCH ( 10 - 1)
+
+// QHD Mode: 960 x 540
+#define QHD_H_RES_PIXELS 960
+#define QHD_V_RES_PIXELS 540
+#define QHD_OSC_FREQUENCY 40750000 /* 0x026DCBB0 */
+#define QHD_H_SYNC ( 96 - 1)
+#define QHD_H_FRONT_PORCH ( 32 - 1)
+#define QHD_H_BACK_PORCH (128 - 1)
+#define QHD_V_SYNC ( 5 - 1)
+#define QHD_V_FRONT_PORCH ( 3 - 1)
+#define QHD_V_BACK_PORCH ( 14 - 1)
+
+// WSVGA Mode: 1024 x 600
+#define WSVGA_H_RES_PIXELS 1024
+#define WSVGA_V_RES_PIXELS 600
+#define WSVGA_OSC_FREQUENCY 49000000 /* 0x02EBAE40 */
+#define WSVGA_H_SYNC (104 - 1)
+#define WSVGA_H_FRONT_PORCH ( 40 - 1)
+#define WSVGA_H_BACK_PORCH (144 - 1)
+#define WSVGA_V_SYNC ( 10 - 1)
+#define WSVGA_V_FRONT_PORCH ( 3 - 1)
+#define WSVGA_V_BACK_PORCH ( 11 - 1)
+
+// HD720 Mode: 1280 x 720
+#define HD720_H_RES_PIXELS 1280
+#define HD720_V_RES_PIXELS 720
+#define HD720_OSC_FREQUENCY 74500000 /* 0x0470C7A0 */
+#define HD720_H_SYNC (128 - 1)
+#define HD720_H_FRONT_PORCH ( 64 - 1)
+#define HD720_H_BACK_PORCH (192 - 1)
+#define HD720_V_SYNC ( 5 - 1)
+#define HD720_V_FRONT_PORCH ( 3 - 1)
+#define HD720_V_BACK_PORCH ( 20 - 1)
+
+// WXGA Mode: 1280 x 800
+#define WXGA_H_RES_PIXELS 1280
+#define WXGA_V_RES_PIXELS 800
+#define WXGA_OSC_FREQUENCY 83500000 /* 0x04FA1BE0 */
+#define WXGA_H_SYNC (128 - 1)
+#define WXGA_H_FRONT_PORCH ( 72 - 1)
+#define WXGA_H_BACK_PORCH (200 - 1)
+#define WXGA_V_SYNC ( 6 - 1)
+#define WXGA_V_FRONT_PORCH ( 3 - 1)
+#define WXGA_V_BACK_PORCH ( 22 - 1)
+
+// Colour Masks
+#define LCD_24BPP_RED_MASK 0x00FF0000
+#define LCD_24BPP_GREEN_MASK 0x0000FF00
+#define LCD_24BPP_BLUE_MASK 0x000000FF
+#define LCD_24BPP_RESERVED_MASK 0xFF000000
+
+#define LCD_16BPP_555_RED_MASK 0x00007C00
+#define LCD_16BPP_555_GREEN_MASK 0x000003E0
+#define LCD_16BPP_555_BLUE_MASK 0x0000001F
+#define LCD_16BPP_555_RESERVED_MASK 0x00000000
+
+#define LCD_16BPP_565_RED_MASK 0x0000F800
+#define LCD_16BPP_565_GREEN_MASK 0x000007E0
+#define LCD_16BPP_565_BLUE_MASK 0x0000001F
+#define LCD_16BPP_565_RESERVED_MASK 0x00008000
+
+#define LCD_12BPP_444_RED_MASK 0x00000F00
+#define LCD_12BPP_444_GREEN_MASK 0x000000F0
+#define LCD_12BPP_444_BLUE_MASK 0x0000000F
+#define LCD_12BPP_444_RESERVED_MASK 0x0000F000
+
+/** The enumeration maps the PL111 LcdBpp values used in the LCD Control
+ Register
+**/
+typedef enum {
+ LCD_BITS_PER_PIXEL_1 = 0,
+ LCD_BITS_PER_PIXEL_2,
+ LCD_BITS_PER_PIXEL_4,
+ LCD_BITS_PER_PIXEL_8,
+ LCD_BITS_PER_PIXEL_16_555,
+ LCD_BITS_PER_PIXEL_24,
+ LCD_BITS_PER_PIXEL_16_565,
+ LCD_BITS_PER_PIXEL_12_444
+} LCD_BPP;
+
+// Display timing settings.
+typedef struct {
+ UINT32 Resolution;
+ UINT32 Sync;
+ UINT32 BackPorch;
+ UINT32 FrontPorch;
+} SCAN_TIMINGS;
+
+/** Platform related initialization function.
+
+ @param[in] Handle Handle to the LCD device instance.
+
+ @retval EFI_SUCCESS Plaform library initialized successfully.
+ @retval !(EFI_SUCCESS) Other errors.
+**/
+EFI_STATUS
+LcdPlatformInitializeDisplay (
+ IN EFI_HANDLE Handle
+ );
+
+/** Allocate VRAM memory in DRAM for the framebuffer
+ (unless it is reserved already).
+
+ The allocated address can be used to set the framebuffer.
+
+ @param[out] VramBaseAddress A pointer to the framebuffer address.
+ @param[out] VramSize A pointer to the size of the frame
+ buffer in bytes
+
+ @retval EFI_SUCCESS Frame buffer memory allocated successfully.
+ @retval !(EFI_SUCCESS) Other errors.
+**/
+EFI_STATUS
+LcdPlatformGetVram (
+ OUT EFI_PHYSICAL_ADDRESS* VramBaseAddress,
+ OUT UINTN* VramSize
+ );
+
+/** Return total number of modes supported.
+
+ Note: Valid mode numbers are 0 to MaxMode - 1
+ See Section 12.9 of the UEFI Specification 2.7
+
+ @retval UINT32 Mode Number.
+**/
+UINT32
+LcdPlatformGetMaxMode (
+ VOID
+ );
+
+/** Set the requested display mode.
+
+ @param[in] ModeNumber Mode Number.
+
+ @retval EFI_SUCCESS Mode set successfully.
+ @retval EFI_INVALID_PARAMETER Requested mode not found.
+ @retval !(EFI_SUCCESS) Other errors.
+**/
+EFI_STATUS
+LcdPlatformSetMode (
+ IN UINT32 ModeNumber
+ );
+
+/** Return information for the requested mode number.
+
+ @param[in] ModeNumber Mode Number.
+ @param[out] Info Pointer for returned mode information
+ (on success).
+
+ @retval EFI_SUCCESS Mode information for the requested mode
+ returned successfully.
+ @retval EFI_INVALID_PARAMETER Requested mode not found.
+**/
+EFI_STATUS
+LcdPlatformQueryMode (
+ IN UINT32 ModeNumber,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
+ );
+
+/** Return display timing information for the requested mode number.
+
+ @param[in] ModeNumber Mode Number.
+
+ @param[out] Horizontal Pointer to horizontal timing parameters.
+ (Resolution, Sync, Back porch, Front porch)
+ @param[out] Vertical Pointer to vertical timing parameters.
+ (Resolution, Sync, Back porch, Front porch)
+
+
+ @retval EFI_SUCCESS Display timing information for the requested
+ mode returned successfully.
+ @retval EFI_INVALID_PARAMETER Requested mode not found.
+**/
+EFI_STATUS
+LcdPlatformGetTimings (
+ IN UINT32 ModeNumber,
+ OUT SCAN_TIMINGS **Horizontal,
+ OUT SCAN_TIMINGS **Vertical
+ );
+
+/** Return bits per pixel information for a mode number.
+
+ @param[in] ModeNumber Mode Number.
+
+ @param[out] Bpp Pointer to value bits per pixel information.
+
+ @retval EFI_SUCCESS Bit per pixel information for the requested
+ mode returned successfully.
+ @retval EFI_INVALID_PARAMETER Requested mode not found.
+**/
+EFI_STATUS
+LcdPlatformGetBpp (
+ IN UINT32 ModeNumber,
+ OUT LCD_BPP* Bpp
+ );
+
+#endif /* LCD_PLATFORM_LIB_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h
new file mode 100644
index 000000000..b26f613a6
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h
@@ -0,0 +1,30 @@
+/** @file
+
+ Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef _NORFLASHPLATFORMLIB_H_
+#define _NORFLASHPLATFORMLIB_H_
+
+typedef struct {
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
+ UINTN RegionBaseAddress; // Start address of one single region
+ UINTN Size;
+ UINTN BlockSize;
+} NOR_FLASH_DESCRIPTION;
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ );
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ );
+
+#endif /* _NORFLASHPLATFORMLIB_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartClockLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartClockLib.h
new file mode 100644
index 000000000..2770688fb
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartClockLib.h
@@ -0,0 +1,25 @@
+/** @file
+*
+* Copyright 2018 NXP
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef __PL011UARTCLOCKLIB_H__
+#define __PL011UARTCLOCKLIB_H__
+
+/**
+
+ Return baud clock frequency of PL011.
+
+ @return return frequency of PL011 in Hz
+
+**/
+UINT32
+EFIAPI
+PL011UartClockGetFreq (
+ VOID
+ );
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartLib.h b/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartLib.h
new file mode 100644
index 000000000..3bd2e294b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Include/Library/PL011UartLib.h
@@ -0,0 +1,183 @@
+/** @file
+*
+* Copyright (c) 2011-2016, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef __PL011_UART_LIB_H__
+#define __PL011_UART_LIB_H__
+
+#include <Uefi/UefiBaseType.h>
+
+#include <Protocol/SerialIo.h>
+
+/**
+
+ Initialise the serial port to the specified settings.
+ All unspecified settings will be set to the default values.
+
+ @param[in] UartBase The base address of the serial device.
+ @param[in] UartClkInHz The clock in Hz for the serial device.
+ Ignored if the PCD PL011UartInteger is not 0
+ @param[in out] BaudRate The baud rate of the serial device. If the
+ baud rate is not supported, the speed will be
+ reduced to the nearest supported one and the
+ variable's value will be updated accordingly.
+ @param[in out] ReceiveFifoDepth The number of characters the device will
+ buffer on input. Value of 0 will use the
+ device's default FIFO depth.
+ @param[in out] Parity If applicable, this is the EFI_PARITY_TYPE
+ that is computed or checked as each character
+ is transmitted or received. If the device
+ does not support parity, the value is the
+ default parity value.
+ @param[in out] DataBits The number of data bits in each character.
+ @param[in out] StopBits If applicable, the EFI_STOP_BITS_TYPE number
+ of stop bits per character.
+ If the device does not support stop bits, the
+ value is the default stop bit value.
+
+ @retval RETURN_SUCCESS All attributes were set correctly on the
+ serial device.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an
+ unsupported value.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartInitializePort (
+ IN UINTN UartBase,
+ IN UINT32 UartClkInHz,
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ );
+
+/**
+
+ Assert or deassert the control signals on a serial port.
+ The following control signals are set according their bit settings :
+ . Request to Send
+ . Data Terminal Ready
+
+ @param[in] UartBase UART registers base address
+ @param[in] Control The following bits are taken into account :
+ . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
+ "Request To Send" control signal if this bit is
+ equal to one/zero.
+ . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
+ the "Data Terminal Ready" control signal if this
+ bit is equal to one/zero.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
+ the hardware loopback if this bit is equal to
+ one/zero.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
+ disable the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals.
+
+ @retval RETURN_SUCCESS The new control bits were set on the device.
+ @retval RETURN_UNSUPPORTED The device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartSetControl (
+ IN UINTN UartBase,
+ IN UINT32 Control
+ );
+
+/**
+
+ Retrieve the status of the control bits on a serial device.
+
+ @param[in] UartBase UART registers base address
+ @param[out] Control Status of the control bits on a serial device :
+
+ . EFI_SERIAL_DATA_CLEAR_TO_SEND,
+ EFI_SERIAL_DATA_SET_READY,
+ EFI_SERIAL_RING_INDICATE,
+ EFI_SERIAL_CARRIER_DETECT,
+ EFI_SERIAL_REQUEST_TO_SEND,
+ EFI_SERIAL_DATA_TERMINAL_READY
+ are all related to the DTE (Data Terminal Equipment)
+ and DCE (Data Communication Equipment) modes of
+ operation of the serial device.
+ . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
+ receive buffer is empty, 0 otherwise.
+ . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
+ transmit buffer is empty, 0 otherwise.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
+ the hardware loopback is enabled (the output feeds the
+ receive buffer), 0 otherwise.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
+ a loopback is accomplished by software, 0 otherwise.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
+ one if the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals is
+ enabled, 0 otherwise.
+
+ @retval RETURN_SUCCESS The control bits were read from the serial device.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartGetControl (
+ IN UINTN UartBase,
+ OUT UINT32 *Control
+ );
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+PL011UartWrite (
+ IN UINTN UartBase,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ );
+
+/**
+ Read data from serial device and save the data in buffer.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+PL011UartRead (
+ IN UINTN UartBase,
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ );
+
+/**
+ Check to see if any data is available to be read from the debug device.
+
+ @retval TRUE At least one byte of data is available to be read
+ @retval FALSE No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+PL011UartPoll (
+ IN UINTN UartBase
+ );
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c
new file mode 100644
index 000000000..23e01f43b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c
@@ -0,0 +1,403 @@
+/** @file
+
+ ARM Mali DP 500/550/650 display controller driver
+
+ Copyright (c) 2017-2018, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/LcdHwLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "ArmMaliDp.h"
+
+// CORE_ID of the MALI DP
+STATIC UINT32 mDpDeviceId;
+
+/** Disable the graphics layer
+
+ This is done by clearing the EN bit of the LG_CONTROL register.
+**/
+STATIC
+VOID
+LayerGraphicsDisable (VOID)
+{
+ MmioAnd32 (DP_BASE + DP_DE_LG_CONTROL, ~DP_DE_LG_ENABLE);
+}
+
+/** Enable the graphics layer
+
+ This is done by setting the EN bit of the LG_CONTROL register.
+**/
+STATIC
+VOID
+LayerGraphicsEnable (VOID)
+{
+ MmioOr32 (DP_BASE + DP_DE_LG_CONTROL, DP_DE_LG_ENABLE);
+}
+
+/** Set the frame address of the graphics layer.
+
+ @param[in] FrameBaseAddress Address of the data buffer to be used as
+ a framebuffer.
+**/
+STATIC
+VOID
+LayerGraphicsSetFrame (
+ IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress
+ )
+{
+ // Disable the graphics layer.
+ LayerGraphicsDisable ();
+
+ // Set up memory address of the data buffer for graphics layer.
+ // write lower bits of the address.
+ MmioWrite32 (
+ DP_BASE + DP_DE_LG_PTR_LOW,
+ DP_DE_LG_PTR_LOW_MASK & FrameBaseAddress
+ );
+
+ // Write higher bits of the address.
+ MmioWrite32 (
+ DP_BASE + DP_DE_LG_PTR_HIGH,
+ (UINT32)(FrameBaseAddress >> DP_DE_LG_PTR_HIGH_SHIFT)
+ );
+
+ // Enable the graphics layer.
+ LayerGraphicsEnable ();
+}
+
+/** Configures various graphics layer characteristics.
+
+ @param[in] UefiGfxPixelFormat This must be either
+ PixelBlueGreenRedReserved8BitPerColor
+ OR
+ PixelRedGreenBlueReserved8BitPerColor
+ @param[in] HRes Horizontal resolution of the graphics layer.
+ @param[in] VRes Vertical resolution of the graphics layer.
+**/
+STATIC
+VOID
+LayerGraphicsConfig (
+ IN CONST EFI_GRAPHICS_PIXEL_FORMAT UefiGfxPixelFormat,
+ IN CONST UINT32 HRes,
+ IN CONST UINT32 VRes
+ )
+{
+ UINT32 PixelFormat;
+
+ // Disable the graphics layer before configuring any settings.
+ LayerGraphicsDisable ();
+
+ // Setup graphics layer size.
+ MmioWrite32 (DP_BASE + DP_DE_LG_IN_SIZE, FRAME_IN_SIZE (HRes, VRes));
+
+ // Setup graphics layer composition size.
+ MmioWrite32 (DP_BASE + DP_DE_LG_CMP_SIZE, FRAME_CMP_SIZE (HRes, VRes));
+
+ // Setup memory stride (total visible pixels on a line * 4).
+ MmioWrite32 (DP_BASE + DP_DE_LG_H_STRIDE, (HRes * sizeof (UINT32)));
+
+ // Set the format.
+
+ // In PixelBlueGreenRedReserved8BitPerColor format, byte 0 represents blue,
+ // byte 1 represents green, byte 2 represents red, and byte 3 is reserved
+ // which is equivalent to XRGB format of the DP500/DP550/DP650. Whereas
+ // PixelRedGreenBlueReserved8BitPerColor is equivalent to XBGR of the
+ // DP500/DP550/DP650.
+ if (UefiGfxPixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+ PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XRGB_8888
+ : DP_PIXEL_FORMAT_XRGB_8888;
+ } else {
+ PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XBGR_8888
+ : DP_PIXEL_FORMAT_XBGR_8888;
+ }
+
+ MmioWrite32 (DP_BASE + DP_DE_LG_FORMAT, PixelFormat);
+
+ // Enable graphics layer.
+ LayerGraphicsEnable ();
+}
+
+/** Configure timing information of the display.
+
+ @param[in] Horizontal Pointer to horizontal timing parameters.
+ (Resolution, Sync, Back porch, Front porch)
+ @param[in] Vertical Pointer to vertical timing parameters.
+ (Resolution, Sync, Back porch, Front porch)
+**/
+STATIC
+VOID
+SetDisplayEngineTiming (
+ IN CONST SCAN_TIMINGS * CONST Horizontal,
+ IN CONST SCAN_TIMINGS * CONST Vertical
+ )
+{
+ UINTN RegHIntervals;
+ UINTN RegVIntervals;
+ UINTN RegSyncControl;
+ UINTN RegHVActiveSize;
+
+ if (mDpDeviceId == MALIDP_500) {
+ // MALI DP500 timing registers.
+ RegHIntervals = DP_BASE + DP_DE_DP500_H_INTERVALS;
+ RegVIntervals = DP_BASE + DP_DE_DP500_V_INTERVALS;
+ RegSyncControl = DP_BASE + DP_DE_DP500_SYNC_CONTROL;
+ RegHVActiveSize = DP_BASE + DP_DE_DP500_HV_ACTIVESIZE;
+ } else {
+ // MALI DP550/DP650 timing registers.
+ RegHIntervals = DP_BASE + DP_DE_H_INTERVALS;
+ RegVIntervals = DP_BASE + DP_DE_V_INTERVALS;
+ RegSyncControl = DP_BASE + DP_DE_SYNC_CONTROL;
+ RegHVActiveSize = DP_BASE + DP_DE_HV_ACTIVESIZE;
+ }
+
+ // Horizontal back porch and front porch.
+ MmioWrite32 (
+ RegHIntervals,
+ H_INTERVALS (Horizontal->FrontPorch, Horizontal->BackPorch)
+ );
+
+ // Vertical back porch and front porch.
+ MmioWrite32 (
+ RegVIntervals,
+ V_INTERVALS (Vertical->FrontPorch, Vertical->BackPorch)
+ );
+
+ // Sync control, Horizontal and Vertical sync.
+ MmioWrite32 (
+ RegSyncControl,
+ SYNC_WIDTH (Horizontal->Sync, Vertical->Sync)
+ );
+
+ // Set up Horizontal and Vertical area size.
+ MmioWrite32 (
+ RegHVActiveSize,
+ HV_ACTIVE (Horizontal->Resolution, Vertical->Resolution)
+ );
+}
+
+/** Return CORE_ID of the ARM Mali DP.
+
+ @retval 0xFFF No Mali DP found.
+ @retval 0x500 Mali DP core id for DP500.
+ @retval 0x550 Mali DP core id for DP550.
+ @retval 0x650 Mali DP core id for DP650.
+**/
+STATIC
+UINT32
+ArmMaliDpGetCoreId (
+ )
+{
+ UINT32 DpCoreId;
+
+ // First check for DP500 as register offset for DP550/DP650 CORE_ID
+ // is beyond 3K/4K register space of the DP500.
+ DpCoreId = MmioRead32 (DP_BASE + DP_DE_DP500_CORE_ID);
+ DpCoreId >>= DP_DE_DP500_CORE_ID_SHIFT;
+
+ if (DpCoreId == MALIDP_500) {
+ return DpCoreId;
+ }
+
+ // Check for DP550 or DP650.
+ DpCoreId = MmioRead32 (DP_BASE + DP_DC_CORE_ID);
+ DpCoreId >>= DP_DC_CORE_ID_SHIFT;
+
+ if ((DpCoreId == MALIDP_550) || (DpCoreId == MALIDP_650)) {
+ return DpCoreId;
+ }
+
+ return MALIDP_NOT_PRESENT;
+}
+
+/** Check for presence of MALI.
+
+ This function returns success if the platform implements
+ DP500/DP550/DP650 ARM Mali display processor.
+
+ @retval EFI_SUCCESS DP500/DP550/DP650 display processor found
+ on the platform.
+ @retval EFI_NOT_FOUND DP500/DP550/DP650 display processor not found
+ on the platform.
+**/
+EFI_STATUS
+LcdIdentify (VOID)
+{
+ DEBUG ((DEBUG_WARN,
+ "Probing ARM Mali DP500/DP550/DP650 at base address 0x%p\n",
+ DP_BASE
+ ));
+
+ if (mDpDeviceId == 0) {
+ mDpDeviceId = ArmMaliDpGetCoreId ();
+ }
+
+ if (mDpDeviceId == MALIDP_NOT_PRESENT) {
+ DEBUG ((DEBUG_WARN, "ARM Mali DP not found...\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ DEBUG ((DEBUG_WARN, "Found ARM Mali DP %x\n", mDpDeviceId));
+ return EFI_SUCCESS;
+}
+
+/** Initialize platform display.
+
+ @param[in] FrameBaseAddress Address of the frame buffer.
+
+ @retval EFI_SUCCESS Display initialization successful.
+ @retval !(EFI_SUCCESS) Display initialization failure.
+**/
+EFI_STATUS
+LcdInitialize (
+ IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress
+ )
+{
+ DEBUG ((DEBUG_WARN, "Framebuffer base address = %p\n", FrameBaseAddress));
+
+ if (mDpDeviceId == 0) {
+ mDpDeviceId = ArmMaliDpGetCoreId ();
+ }
+
+ if (mDpDeviceId == MALIDP_NOT_PRESENT) {
+ DEBUG ((DEBUG_ERROR, "ARM Mali DP initialization failed,"
+ "no ARM Mali DP present\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ // We are using graphics layer of the Mali DP as a main framebuffer.
+ LayerGraphicsSetFrame (FrameBaseAddress);
+
+ return EFI_SUCCESS;
+}
+
+/** Set ARM Mali DP in cofiguration mode.
+
+ The ARM Mali DP must be in the configuration mode for
+ configuration of the H_INTERVALS, V_INTERVALS, SYNC_CONTROL
+ and HV_ACTIVESIZE.
+**/
+STATIC
+VOID
+SetConfigurationMode (VOID)
+{
+ // Request configuration Mode.
+ if (mDpDeviceId == MALIDP_500) {
+ MmioOr32 (DP_BASE + DP_DE_DP500_CONTROL, DP_DE_DP500_CONTROL_CONFIG_REQ);
+ } else {
+ MmioOr32 (DP_BASE + DP_DC_CONTROL, DP_DC_CONTROL_CM_ACTIVE);
+ }
+}
+
+/** Set ARM Mali DP in normal mode.
+
+ Normal mode is the main operating mode of the display processor
+ in which display layer data is fetched from framebuffer and
+ displayed.
+**/
+STATIC
+VOID
+SetNormalMode (VOID)
+{
+ // Disable configuration Mode.
+ if (mDpDeviceId == MALIDP_500) {
+ MmioAnd32 (DP_BASE + DP_DE_DP500_CONTROL, ~DP_DE_DP500_CONTROL_CONFIG_REQ);
+ } else {
+ MmioAnd32 (DP_BASE + DP_DC_CONTROL, ~DP_DC_CONTROL_CM_ACTIVE);
+ }
+}
+
+/** Set the global configuration valid flag.
+
+ Any new configuration parameters written to the display engine are not
+ activated until the global configuration valid flag is set in the
+ CONFIG_VALID register.
+**/
+STATIC
+VOID
+SetConfigValid (VOID)
+{
+ if (mDpDeviceId == MALIDP_500) {
+ MmioOr32 (DP_BASE + DP_DP500_CONFIG_VALID, DP_DC_CONFIG_VALID);
+ } else {
+ MmioOr32 (DP_BASE + DP_DC_CONFIG_VALID, DP_DC_CONFIG_VALID);
+ }
+}
+
+/** Set requested mode of the display.
+
+ @param[in] ModeNumber Display mode number.
+
+ @retval EFI_SUCCESS Display mode set successful.
+ @retval EFI_DEVICE_ERROR Display mode not found/supported.
+**/
+EFI_STATUS
+LcdSetMode (
+ IN CONST UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status;
+ SCAN_TIMINGS *Horizontal;
+ SCAN_TIMINGS *Vertical;
+
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
+
+ // Get the display mode timings and other relevant information.
+ Status = LcdPlatformGetTimings (
+ ModeNumber,
+ &Horizontal,
+ &Vertical
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ ASSERT (Horizontal != NULL);
+ ASSERT (Vertical != NULL);
+
+ // Get the pixel format information.
+ Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Request configuration mode.
+ SetConfigurationMode ();
+
+ // Configure the graphics layer.
+ LayerGraphicsConfig (
+ ModeInfo.PixelFormat,
+ Horizontal->Resolution,
+ Vertical->Resolution
+ );
+
+ // Set the display engine timings.
+ SetDisplayEngineTiming (Horizontal, Vertical);
+
+ // After configuration, set Mali DP in normal mode.
+ SetNormalMode ();
+
+ // Any parameters written to the display engine are not activated until
+ // CONFIG_VALID is set.
+ SetConfigValid ();
+
+ return EFI_SUCCESS;
+}
+
+/** This function de-initializes the display.
+
+**/
+VOID
+LcdShutdown (VOID)
+{
+ // Disable graphics layer.
+ LayerGraphicsDisable ();
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h
new file mode 100644
index 000000000..7939b0ff5
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h
@@ -0,0 +1,237 @@
+/** @file
+
+ This header file contains the platform independent parts of ARM Mali DP
+
+ Copyright (c) 2017-2018, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef ARMMALIDP_H_
+#define ARMMALIDP_H_
+
+#define DP_BASE (FixedPcdGet64 (PcdArmMaliDpBase))
+
+// MALI DP Ids
+#define MALIDP_NOT_PRESENT 0xFFF
+#define MALIDP_500 0x500
+#define MALIDP_550 0x550
+#define MALIDP_650 0x650
+
+// DP500 Peripheral Ids
+#define DP500_ID_PART_0 0x00
+#define DP500_ID_DES_0 0xB
+#define DP500_ID_PART_1 0x5
+
+#define DP500_ID_REVISION 0x1
+#define DP500_ID_JEDEC 0x1
+#define DP500_ID_DES_1 0x3
+
+#define DP500_PERIPHERAL_ID0_VAL (DP500_ID_PART_0)
+#define DP500_PERIPHERAL_ID1_VAL ((DP500_ID_DES_0 << 4) \
+ | DP500_ID_PART_1)
+#define DP500_PERIPHERAL_ID2_VAL ((DP500_ID_REVISION << 4) \
+ | (DP500_ID_JEDEC << 3) \
+ | (DP500_ID_DES_1))
+
+// DP550 Peripheral Ids
+#define DP550_ID_PART_0 0x50
+#define DP550_ID_DES_0 0xB
+#define DP550_ID_PART_1 0x5
+
+#define DP550_ID_REVISION 0x0
+#define DP550_ID_JEDEC 0x1
+#define DP550_ID_DES_1 0x3
+
+#define DP550_PERIPHERAL_ID0_VAL (DP550_ID_PART_0)
+#define DP550_PERIPHERAL_ID1_VAL ((DP550_ID_DES_0 << 4) \
+ | DP550_ID_PART_1)
+#define DP550_PERIPHERAL_ID2_VAL ((DP550_ID_REVISION << 4) \
+ | (DP550_ID_JEDEC << 3) \
+ | (DP550_ID_DES_1))
+
+// DP650 Peripheral Ids
+#define DP650_ID_PART_0 0x50
+#define DP650_ID_DES_0 0xB
+#define DP650_ID_PART_1 0x6
+
+#define DP650_ID_REVISION 0x0
+#define DP650_ID_JEDEC 0x1
+#define DP650_ID_DES_1 0x3
+
+#define DP650_PERIPHERAL_ID0_VAL (DP650_ID_PART_0)
+#define DP650_PERIPHERAL_ID1_VAL ((DP650_ID_DES_0 << 4) \
+ | DP650_ID_PART_1)
+#define DP650_PERIPHERAL_ID2_VAL ((DP650_ID_REVISION << 4) \
+ | (DP650_ID_JEDEC << 3) \
+ | (DP650_ID_DES_1))
+
+// Display Engine (DE) control register offsets for DP550/DP650
+#define DP_DE_STATUS 0x00000
+#define DP_DE_IRQ_SET 0x00004
+#define DP_DE_IRQ_MASK 0x00008
+#define DP_DE_IRQ_CLEAR 0x0000C
+#define DP_DE_CONTROL 0x00010
+#define DP_DE_PROG_LINE 0x00014
+#define DP_DE_AXI_CONTROL 0x00018
+#define DP_DE_AXI_QOS 0x0001C
+#define DP_DE_DISPLAY_FUNCTION 0x00020
+
+#define DP_DE_H_INTERVALS 0x00030
+#define DP_DE_V_INTERVALS 0x00034
+#define DP_DE_SYNC_CONTROL 0x00038
+#define DP_DE_HV_ACTIVESIZE 0x0003C
+#define DP_DE_DISPLAY_SIDEBAND 0x00040
+#define DP_DE_BACKGROUND_COLOR 0x00044
+#define DP_DE_DISPLAY_SPLIT 0x00048
+#define DP_DE_OUTPUT_DEPTH 0x0004C
+
+// Display Engine (DE) control register offsets for DP500
+#define DP_DE_DP500_CORE_ID 0x00018
+#define DP_DE_DP500_CONTROL 0x0000C
+#define DP_DE_DP500_PROG_LINE 0x00010
+#define DP_DE_DP500_H_INTERVALS 0x00028
+#define DP_DE_DP500_V_INTERVALS 0x0002C
+#define DP_DE_DP500_SYNC_CONTROL 0x00030
+#define DP_DE_DP500_HV_ACTIVESIZE 0x00034
+#define DP_DE_DP500_BG_COLOR_RG 0x0003C
+#define DP_DE_DP500_BG_COLOR_B 0x00040
+
+/* Display Engine (DE) graphics layer (LG) register offsets
+ * NOTE: For DP500 it will be LG2.
+ */
+#define DE_LG_OFFSET 0x00300
+#define DP_DE_LG_FORMAT (DE_LG_OFFSET)
+#define DP_DE_LG_CONTROL (DE_LG_OFFSET + 0x04)
+#define DP_DE_LG_COMPOSE (DE_LG_OFFSET + 0x08)
+#define DP_DE_LG_IN_SIZE (DE_LG_OFFSET + 0x0C)
+#define DP_DE_LG_CMP_SIZE (DE_LG_OFFSET + 0x10)
+#define DP_DE_LG_OFFSET (DE_LG_OFFSET + 0x14)
+#define DP_DE_LG_H_STRIDE (DE_LG_OFFSET + 0x18)
+#define DP_DE_LG_PTR_LOW (DE_LG_OFFSET + 0x1C)
+#define DP_DE_LG_PTR_HIGH (DE_LG_OFFSET + 0x20)
+#define DP_DE_LG_CHROMA_KEY (DE_LG_OFFSET + 0x2C)
+#define DP_DE_LG_AD_CONTROL (DE_LG_OFFSET + 0x30)
+#define DP_DE_LG_MMU_CONTROL (DE_LG_OFFSET + 0x48)
+
+// Display core (DC) control register offsets.
+#define DP_DC_OFFSET 0x0C000
+#define DP_DC_STATUS (DP_DC_OFFSET + 0x00)
+#define DP_DC_IRQ_SET (DP_DC_OFFSET + 0x04)
+#define DP_DC_IRQ_MASK (DP_DC_OFFSET + 0x08)
+#define DP_DC_IRQ_CLEAR (DP_DC_OFFSET + 0x0C)
+#define DP_DC_CONTROL (DP_DC_OFFSET + 0x10)
+#define DP_DC_CONFIG_VALID (DP_DC_OFFSET + 0x14)
+#define DP_DC_CORE_ID (DP_DC_OFFSET + 0x18)
+
+// DP500 has a global configuration register.
+#define DP_DP500_CONFIG_VALID (0xF00)
+
+// Display core ID register offsets.
+#define DP_DC_ID_OFFSET 0x0FF00
+#define DP_DC_ID_PERIPHERAL_ID4 (DP_DC_ID_OFFSET + 0xD0)
+#define DP_DC_CONFIGURATION_ID (DP_DC_ID_OFFSET + 0xD4)
+#define DP_DC_PERIPHERAL_ID0 (DP_DC_ID_OFFSET + 0xE0)
+#define DP_DC_PERIPHERAL_ID1 (DP_DC_ID_OFFSET + 0xE4)
+#define DP_DC_PERIPHERAL_ID2 (DP_DC_ID_OFFSET + 0xE8)
+#define DP_DC_COMPONENT_ID0 (DP_DC_ID_OFFSET + 0xF0)
+#define DP_DC_COMPONENT_ID1 (DP_DC_ID_OFFSET + 0xF4)
+#define DP_DC_COMPONENT_ID2 (DP_DC_ID_OFFSET + 0xF8)
+#define DP_DC_COMPONENT_ID3 (DP_DC_ID_OFFSET + 0xFC)
+
+#define DP_DP500_ID_OFFSET 0x0F00
+#define DP_DP500_ID_PERIPHERAL_ID4 (DP_DP500_ID_OFFSET + 0xD0)
+#define DP_DP500_CONFIGURATION_ID (DP_DP500_ID_OFFSET + 0xD4)
+#define DP_DP500_PERIPHERAL_ID0 (DP_DP500_ID_OFFSET + 0xE0)
+#define DP_DP500_PERIPHERAL_ID1 (DP_DP500_ID_OFFSET + 0xE4)
+#define DP_DP500_PERIPHERAL_ID2 (DP_DP500_ID_OFFSET + 0xE8)
+#define DP_DP500_COMPONENT_ID0 (DP_DP500_ID_OFFSET + 0xF0)
+#define DP_DP500_COMPONENT_ID1 (DP_DP500_ID_OFFSET + 0xF4)
+#define DP_DP500_COMPONENT_ID2 (DP_DP500_ID_OFFSET + 0xF8)
+#define DP_DP500_COMPONENT_ID3 (DP_DP500_ID_OFFSET + 0xFC)
+
+// Display status configuration mode activation flag
+#define DP_DC_STATUS_CM_ACTIVE_FLAG (0x1U << 16)
+
+// Display core control configuration mode
+#define DP_DC_CONTROL_SRST_ACTIVE (0x1U << 18)
+#define DP_DC_CONTROL_CRST_ACTIVE (0x1U << 17)
+#define DP_DC_CONTROL_CM_ACTIVE (0x1U << 16)
+
+#define DP_DE_DP500_CONTROL_SOFTRESET_REQ (0x1U << 16)
+#define DP_DE_DP500_CONTROL_CONFIG_REQ (0x1U << 17)
+
+// Display core configuration valid register
+#define DP_DC_CONFIG_VALID_CVAL (0x1U)
+
+// DC_CORE_ID
+// Display core version register PRODUCT_ID
+#define DP_DC_CORE_ID_SHIFT 16
+#define DP_DE_DP500_CORE_ID_SHIFT DP_DC_CORE_ID_SHIFT
+
+// Timing settings
+#define DP_DE_HBACKPORCH_SHIFT 16
+#define DP_DE_VBACKPORCH_SHIFT 16
+#define DP_DE_VSP_SHIFT 28
+#define DP_DE_VSYNCWIDTH_SHIFT 16
+#define DP_DE_HSP_SHIFT 13
+#define DP_DE_V_ACTIVE_SHIFT 16
+
+// BACKGROUND_COLOR
+#define DP_DE_BG_R_PIXEL_SHIFT 16
+#define DP_DE_BG_G_PIXEL_SHIFT 8
+
+//Graphics layer LG_FORMAT Pixel Format
+#define DP_PIXEL_FORMAT_ARGB_8888 0x8
+#define DP_PIXEL_FORMAT_ABGR_8888 0x9
+#define DP_PIXEL_FORMAT_RGBA_8888 0xA
+#define DP_PIXEL_FORMAT_BGRA_8888 0xB
+#define DP_PIXEL_FORMAT_XRGB_8888 0x10
+#define DP_PIXEL_FORMAT_XBGR_8888 0x11
+#define DP_PIXEL_FORMAT_RGBX_8888 0x12
+#define DP_PIXEL_FORMAT_BGRX_8888 0x13
+#define DP_PIXEL_FORMAT_RGB_888 0x18
+#define DP_PIXEL_FORMAT_BGR_888 0x19
+
+// DP500 format code are different than DP550/DP650
+#define DP_PIXEL_FORMAT_DP500_ARGB_8888 0x2
+#define DP_PIXEL_FORMAT_DP500_ABGR_8888 0x3
+#define DP_PIXEL_FORMAT_DP500_XRGB_8888 0x4
+#define DP_PIXEL_FORMAT_DP500_XBGR_8888 0x5
+
+// Graphics layer LG_PTR_LOW and LG_PTR_HIGH
+#define DP_DE_LG_PTR_LOW_MASK 0xFFFFFFFFU
+#define DP_DE_LG_PTR_HIGH_SHIFT 32
+
+// Graphics layer LG_CONTROL register characteristics
+#define DP_DE_LG_L_ALPHA_SHIFT 16
+#define DP_DE_LG_CHK_SHIFT 15
+#define DP_DE_LG_PMUL_SHIFT 14
+#define DP_DE_LG_COM_SHIFT 12
+#define DP_DE_LG_VFP_SHIFT 11
+#define DP_DE_LG_HFP_SHIFT 10
+#define DP_DE_LG_ROTATION_SHIFT 8
+
+#define DP_DE_LG_LAYER_BLEND_NO_BG 0x0U
+#define DP_DE_LG_PIXEL_BLEND_NO_BG 0x1U
+#define DP_DE_LG_LAYER_BLEND_BG 0x2U
+#define DP_DE_LG_PIXEL_BLEND_BG 0x3U
+#define DP_DE_LG_ENABLE 0x1U
+
+// Graphics layer LG_IN_SIZE register characteristics
+#define DP_DE_LG_V_IN_SIZE_SHIFT 16
+
+// Graphics layer LG_CMP_SIZE register characteristics
+#define DP_DE_LG_V_CMP_SIZE_SHIFT 16
+#define DP_DE_LG_V_OFFSET_SHIFT 16
+
+// Helper display timing macro functions.
+#define H_INTERVALS(Hfp, Hbp) ((Hbp << DP_DE_HBACKPORCH_SHIFT) | Hfp)
+#define V_INTERVALS(Vfp, Vbp) ((Vbp << DP_DE_VBACKPORCH_SHIFT) | Vfp)
+#define SYNC_WIDTH(Hsw, Vsw) ((Vsw << DP_DE_VSYNCWIDTH_SHIFT) | Hsw)
+#define HV_ACTIVE(Hor, Ver) ((Ver << DP_DE_V_ACTIVE_SHIFT) | Hor)
+
+// Helper layer graphics macros.
+#define FRAME_IN_SIZE(Hor, Ver) ((Ver << DP_DE_LG_V_IN_SIZE_SHIFT) | Hor)
+#define FRAME_CMP_SIZE(Hor, Ver) ((Ver << DP_DE_LG_V_CMP_SIZE_SHIFT) | Hor)
+
+#endif /* ARMMALIDP_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf
new file mode 100644
index 000000000..d9d9bbd30
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf
@@ -0,0 +1,38 @@
+#/** @file
+#
+# Component description file for ArmMaliDp module
+#
+# Copyright (c) 2017-2018, Arm Limited. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = ArmMaliDp
+ FILE_GUID = E724AAF7-19E2-40A3-BAE1-D82A7C8B7A76
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LcdHwLib
+
+[Sources.common]
+ ArmMaliDp.h
+ ArmMaliDp.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ LcdPlatformLib
+ UefiLib
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdArmMaliDpBase
+
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/AArch64/ArmPlatformHelper.S b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/AArch64/ArmPlatformHelper.S
new file mode 100644
index 000000000..b7c6dbdc2
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/AArch64/ArmPlatformHelper.S
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+#include <Library/ArmLib.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+ 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
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+ MOV32 (w0, FixedPcdGet32 (PcdArmPrimaryCore))
+ ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+ MOV32 (w1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+ and x0, x0, x1
+ MOV32 (w1, FixedPcdGet32 (PcdArmPrimaryCore))
+ cmp w0, w1
+ mov x0, #1
+ mov x1, #0
+ csel x0, x0, x1, eq
+ ret
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.S b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.S
new file mode 100644
index 000000000..aedae5562
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.S
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLib.h>
+#include <Library/ArmLib.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+ bx lr
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+ASM_FUNC(ArmPlatformGetCorePosition)
+ and r1, r0, #ARM_CORE_MASK
+ and r0, r0, #ARM_CLUSTER_MASK
+ add r0, r1, r0, LSR #7
+ bx lr
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+ MOV32 (r0, FixedPcdGet32 (PcdArmPrimaryCore))
+ bx lr
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+ MOV32 (r1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+ and r0, r0, r1
+ MOV32 (r1, FixedPcdGet32 (PcdArmPrimaryCore))
+ cmp r0, r1
+ moveq r0, #1
+ movne r0, #0
+ bx lr
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.asm b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.asm
new file mode 100644
index 000000000..1c305f8b5
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.asm
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <Library/ArmLib.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT ArmPlatformPeiBootAction
+ EXPORT ArmPlatformGetCorePosition
+ EXPORT ArmPlatformGetPrimaryCoreMpId
+ EXPORT ArmPlatformIsPrimaryCore
+
+ IMPORT _gPcd_FixedAtBuild_PcdArmPrimaryCore
+ IMPORT _gPcd_FixedAtBuild_PcdArmPrimaryCoreMask
+
+ PRESERVE8
+ AREA ArmPlatformNullHelper, CODE, READONLY
+
+ArmPlatformPeiBootAction FUNCTION
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+ArmPlatformGetCorePosition FUNCTION
+ and r1, r0, #ARM_CORE_MASK
+ and r0, r0, #ARM_CLUSTER_MASK
+ add r0, r1, r0, LSR #7
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ArmPlatformGetPrimaryCoreMpId FUNCTION
+ mov32 r0, FixedPcdGet32(PcdArmPrimaryCore)
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ArmPlatformIsPrimaryCore FUNCTION
+ mov32 r1, FixedPcdGet32(PcdArmPrimaryCoreMask)
+ and r0, r0, r1
+ mov32 r1, FixedPcdGet32(PcdArmPrimaryCore)
+ cmp r0, r1
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+ ENDFUNC
+
+ END
+
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.c b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.c
new file mode 100644
index 000000000..6c21792cf
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.c
@@ -0,0 +1,142 @@
+/** @file
+*
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/ArmLib.h>
+#include <Library/ArmPlatformLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+
+ARM_CORE_INFO mArmPlatformNullMpCoreInfoTable[] = {
+ {
+ // Cluster 0, Core 0
+ 0x0, 0x0,
+
+ // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (UINT64)0xFFFFFFFF
+ },
+ {
+ // Cluster 0, Core 1
+ 0x0, 0x1,
+
+ // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (UINT64)0xFFFFFFFF
+ },
+ {
+ // Cluster 0, Core 2
+ 0x0, 0x2,
+
+ // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (UINT64)0xFFFFFFFF
+ },
+ {
+ // Cluster 0, Core 3
+ 0x0, 0x3,
+
+ // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (UINT64)0xFFFFFFFF
+ }
+};
+
+// This function should be better located into TimerLib implementation
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the current Boot Mode
+
+ This function returns the boot reason on 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/PrePi or ArmPlatformPkg/PlatformPei
+ in the PEI phase.
+
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ )
+{
+ if (!ArmPlatformIsPrimaryCore (MpId)) {
+ return RETURN_SUCCESS;
+ }
+
+ //TODO: Implement me
+
+ return RETURN_SUCCESS;
+}
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+ OUT UINTN *CoreCount,
+ OUT ARM_CORE_INFO **ArmCoreTable
+ )
+{
+ if (ArmIsMpCore()) {
+ *CoreCount = sizeof(mArmPlatformNullMpCoreInfoTable) / sizeof(ARM_CORE_INFO);
+ *ArmCoreTable = mArmPlatformNullMpCoreInfoTable;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
+
+EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gArmMpCoreInfoPpiGuid,
+ &mMpCoreInfoPpi
+ }
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ if (ArmIsMpCore()) {
+ *PpiListSize = sizeof(gPlatformPpiTable);
+ *PpiList = gPlatformPpiTable;
+ } else {
+ *PpiListSize = 0;
+ *PpiList = NULL;
+ }
+}
+
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
new file mode 100644
index 000000000..e0d0028d8
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
@@ -0,0 +1,42 @@
+#/* @file
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformLibNull
+ FILE_GUID = cb494bad-23ff-427e-8608-d7e138d3363b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ DebugLib
+
+[Sources.common]
+ ArmPlatformLibNull.c
+ ArmPlatformLibNullMem.c
+
+[Sources.Arm]
+ Arm/ArmPlatformHelper.S | GCC
+ Arm/ArmPlatformHelper.asm | RVCT
+
+[Sources.AArch64]
+ AArch64/ArmPlatformHelper.S
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+[Ppis]
+ gArmMpCoreInfoPpiGuid
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNullMem.c b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNullMem.c
new file mode 100644
index 000000000..5109ff693
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNullMem.c
@@ -0,0 +1,28 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ 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
+ )
+{
+ ASSERT(0);
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/AArch64/ArmPlatformStackLib.S b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/AArch64/ArmPlatformStackLib.S
new file mode 100644
index 000000000..db0912c19
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/AArch64/ArmPlatformStackLib.S
@@ -0,0 +1,99 @@
+//
+// Copyright (c) 2012-2014, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+
+//VOID
+//ArmPlatformStackSet (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSet)
+ // Save parameters
+ mov x26, x3
+ mov x25, x2
+ mov x24, x1
+ mov x23, x0
+
+ // Save the Link register
+ mov x27, x30
+
+ // Identify Stack
+ mov x0, x1
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+ cmp x0, #1
+
+ // Restore parameters
+ mov x0, x23
+ mov x1, x24
+ mov x2, x25
+ mov x3, x26
+
+ // Restore the Link register
+ mov x30, x27
+
+ b.ne 0f
+
+ b ASM_PFX(ArmPlatformStackSetPrimary)
+0:b ASM_PFX(ArmPlatformStackSetSecondary)
+
+//VOID
+//ArmPlatformStackSetPrimary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSetPrimary)
+ // Add size of primary stack to StackBase
+ add x0, x0, x2
+
+ // Compute SecondaryCoresCount * SecondaryCoreStackSize
+ MOV32 (w1, FixedPcdGet32(PcdCoreCount) - 1)
+ mul x3, x3, x1
+
+ // Set Primary Stack ((StackBase + PrimaryStackSize) + (SecondaryCoresCount * SecondaryCoreStackSize))
+ add sp, x0, x3
+
+ ret
+
+//VOID
+//ArmPlatformStackSetSecondary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSetSecondary)
+ // Save the Link register
+ mov x24, x30
+ mov sp, x0
+
+ // Get Core Position
+ mov x0, x1
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+ mov x25, x0
+
+ // Get Primary Core Position
+ bl ASM_PFX(ArmPlatformGetPrimaryCoreMpId)
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+
+ // Get Secondary Core Position. We should get consecutive secondary stack number from 1...(CoreCount-1)
+ cmp x25, x0
+
+ // Decrement the position if after the primary core
+ cinc x25, x25, ls
+
+ // Compute top of the secondary stack
+ mul x3, x3, x25
+
+ // Set stack
+ add sp, sp, x3
+
+ ret x24
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.S b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.S
new file mode 100644
index 000000000..0e47032ed
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.S
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLib.h>
+
+//VOID
+//ArmPlatformStackSet (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSet)
+ // Save parameters
+ mov r6, r3
+ mov r5, r2
+ mov r4, r1
+ mov r3, r0
+
+ // Save the Link register
+ mov r7, lr
+
+ // Identify Stack
+ mov r0, r1
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+ cmp r0, #1
+
+ // Restore parameters
+ mov r0, r3
+ mov r1, r4
+ mov r2, r5
+ mov r3, r6
+
+ // Restore the Link register
+ mov lr, r7
+
+ beq ASM_PFX(ArmPlatformStackSetPrimary)
+ bne ASM_PFX(ArmPlatformStackSetSecondary)
+
+//VOID
+//ArmPlatformStackSetPrimary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSetPrimary)
+ mov r4, lr
+
+ // Add stack of primary stack to StackBase
+ add r0, r0, r2
+
+ // Compute SecondaryCoresCount * SecondaryCoreStackSize
+ MOV32 (r1, FixedPcdGet32(PcdCoreCount) - 1)
+ mul r3, r3, r1
+
+ // Set Primary Stack ((StackBase + PrimaryStackSize) + (SecondaryCoresCount * SecondaryCoreStackSize))
+ add sp, r0, r3
+
+ bx r4
+
+//VOID
+//ArmPlatformStackSetSecondary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ASM_FUNC(ArmPlatformStackSetSecondary)
+ mov r4, lr
+ mov sp, r0
+
+ // Get Core Position
+ mov r0, r1
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+ mov r5, r0
+
+ // Get Primary Core Position
+ bl ASM_PFX(ArmPlatformGetPrimaryCoreMpId)
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+
+ // Get Secondary Core Position. We should get consecutive secondary stack number from 1...(CoreCount-1)
+ cmp r5, r0
+ subhi r5, r5, #1
+ add r5, r5, #1
+
+ // Compute top of the secondary stack
+ mul r3, r3, r5
+
+ // Set stack
+ add sp, sp, r3
+
+ bx r4
+
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.asm b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.asm
new file mode 100644
index 000000000..2c346146d
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.asm
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT ArmPlatformStackSet
+ EXPORT ArmPlatformStackSetPrimary
+ EXPORT ArmPlatformStackSetSecondary
+
+ IMPORT ArmPlatformIsPrimaryCore
+ IMPORT ArmPlatformGetCorePosition
+ IMPORT ArmPlatformGetPrimaryCoreMpId
+
+ IMPORT _gPcd_FixedAtBuild_PcdCoreCount
+
+ PRESERVE8
+ AREA ArmPlatformStackLib, CODE, READONLY
+
+//VOID
+//ArmPlatformStackSet (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ArmPlatformStackSet FUNCTION
+ // Save parameters
+ mov r6, r3
+ mov r5, r2
+ mov r4, r1
+ mov r3, r0
+
+ // Save the Link register
+ mov r7, lr
+
+ // Identify Stack
+ mov r0, r1
+ bl ArmPlatformIsPrimaryCore
+ cmp r0, #1
+
+ // Restore parameters
+ mov r0, r3
+ mov r1, r4
+ mov r2, r5
+ mov r3, r6
+
+ // Restore the Link register
+ mov lr, r7
+
+ beq ArmPlatformStackSetPrimary
+ bne ArmPlatformStackSetSecondary
+ ENDFUNC
+
+//VOID
+//ArmPlatformStackSetPrimary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ArmPlatformStackSetPrimary FUNCTION
+ mov r4, lr
+
+ // Add stack of primary stack to StackBase
+ add r0, r0, r2
+
+ // Compute SecondaryCoresCount * SecondaryCoreStackSize
+ mov32 r1, FixedPcdGet32 (PcdCoreCount)
+ sub r1, #1
+ mul r3, r3, r1
+
+ // Set Primary Stack ((StackBase + PrimaryStackSize) + (SecondaryCoresCount * SecondaryCoreStackSize))
+ add sp, r0, r3
+
+ bx r4
+ ENDFUNC
+
+//VOID
+//ArmPlatformStackSetSecondary (
+// IN UINTN StackBase,
+// IN UINTN MpId,
+// IN UINTN PrimaryStackSize,
+// IN UINTN SecondaryStackSize
+// );
+ArmPlatformStackSetSecondary FUNCTION
+ mov r4, lr
+ mov sp, r0
+
+ // Get Core Position
+ mov r0, r1
+ bl ArmPlatformGetCorePosition
+ mov r5, r0
+
+ // Get Primary Core Position
+ bl ArmPlatformGetPrimaryCoreMpId
+ bl ArmPlatformGetCorePosition
+
+ // Get Secondary Core Position. We should get consecutive secondary stack number from 1...(CoreCount-1)
+ cmp r5, r0
+ subhi r5, r5, #1
+ add r5, r5, #1
+
+ // Compute top of the secondary stack
+ mul r3, r3, r5
+
+ // Set stack
+ add sp, sp, r3
+
+ bx r4
+ ENDFUNC
+
+ END
diff --git a/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
new file mode 100644
index 000000000..76f809c80
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
@@ -0,0 +1,34 @@
+#/* @file
+#
+# Copyright (c) 2012, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformStackLib
+ FILE_GUID = 5e2e44af-53c1-44c2-a801-9c149f3d6ba0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformStackLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[Sources.ARM]
+ Arm/ArmPlatformStackLib.asm | RVCT
+ Arm/ArmPlatformStackLib.S | GCC
+
+[Sources.AARCH64]
+ AArch64/ArmPlatformStackLib.S
+
+[LibraryClasses]
+ ArmPlatformLib
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
diff --git a/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c
new file mode 100644
index 000000000..0247057e6
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c
@@ -0,0 +1,174 @@
+/** @file
+ This file contains the platform independent parts of HdLcd
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/LcdHwLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include "HdLcd.h"
+
+#define BYTES_PER_PIXEL 4
+
+/** Initialize display.
+
+ @param[in] VramBaseAddress Address of the framebuffer.
+
+ @retval EFI_SUCCESS Display initialization successful.
+**/
+EFI_STATUS
+LcdInitialize (
+ IN EFI_PHYSICAL_ADDRESS VramBaseAddress
+ )
+{
+ // Disable the controller
+ MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
+
+ // Disable all interrupts
+ MmioWrite32 (HDLCD_REG_INT_MASK, 0);
+
+ // Define start of the VRAM. This never changes for any graphics mode
+ MmioWrite32 (HDLCD_REG_FB_BASE, (UINT32)VramBaseAddress);
+
+ // Setup various registers that never change
+ MmioWrite32 (HDLCD_REG_BUS_OPTIONS, (4 << 8) | HDLCD_BURST_8);
+
+ MmioWrite32 (HDLCD_REG_POLARITIES, HDLCD_DEFAULT_POLARITIES);
+
+ MmioWrite32 (
+ HDLCD_REG_PIXEL_FORMAT,
+ HDLCD_LITTLE_ENDIAN | HDLCD_4BYTES_PER_PIXEL
+ );
+
+ return EFI_SUCCESS;
+}
+
+/** Set requested mode of the display.
+
+ @param[in] ModeNumber Display mode number.
+
+ @retval EFI_SUCCESS Display mode set successfully.
+ @retval !(EFI_SUCCESS) Other errors.
+**/
+EFI_STATUS
+LcdSetMode (
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status;
+ SCAN_TIMINGS *Horizontal;
+ SCAN_TIMINGS *Vertical;
+
+ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
+
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
+
+ // Set the video mode timings and other relevant information
+ Status = LcdPlatformGetTimings (
+ ModeNumber,
+ &Horizontal,
+ &Vertical
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ ASSERT (Horizontal != NULL);
+ ASSERT (Vertical != NULL);
+
+ // Get the pixel format information.
+ Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // By default PcdArmHdLcdSwapBlueRedSelect is set to false
+ // However on the Juno platform HW lines for BLUE and RED are swapped
+ // Therefore PcdArmHdLcdSwapBlueRedSelect is set to TRUE for the Juno platform
+ PixelFormat = FixedPcdGetBool (PcdArmHdLcdSwapBlueRedSelect)
+ ? PixelRedGreenBlueReserved8BitPerColor
+ : PixelBlueGreenRedReserved8BitPerColor;
+
+ if (ModeInfo.PixelFormat == PixelFormat) {
+ MmioWrite32 (HDLCD_REG_RED_SELECT, (8 << 8) | 16);
+ MmioWrite32 (HDLCD_REG_BLUE_SELECT, (8 << 8) | 0);
+ } else {
+ MmioWrite32 (HDLCD_REG_BLUE_SELECT, (8 << 8) | 16);
+ MmioWrite32 (HDLCD_REG_RED_SELECT, (8 << 8) | 0);
+ }
+
+ MmioWrite32 (HDLCD_REG_GREEN_SELECT, (8 << 8) | 8);
+
+ // Disable the controller
+ MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
+
+ // Update the frame buffer information with the new settings
+ MmioWrite32 (
+ HDLCD_REG_FB_LINE_LENGTH,
+ Horizontal->Resolution * BYTES_PER_PIXEL
+ );
+
+ MmioWrite32 (
+ HDLCD_REG_FB_LINE_PITCH,
+ Horizontal->Resolution * BYTES_PER_PIXEL
+ );
+
+ MmioWrite32 (HDLCD_REG_FB_LINE_COUNT, Vertical->Resolution - 1);
+
+ // Set the vertical timing information
+ MmioWrite32 (HDLCD_REG_V_SYNC, Vertical->Sync);
+ MmioWrite32 (HDLCD_REG_V_BACK_PORCH, Vertical->BackPorch);
+ MmioWrite32 (HDLCD_REG_V_DATA, Vertical->Resolution - 1);
+ MmioWrite32 (HDLCD_REG_V_FRONT_PORCH, Vertical->FrontPorch);
+
+ // Set the horizontal timing information
+ MmioWrite32 (HDLCD_REG_H_SYNC, Horizontal->Sync);
+ MmioWrite32 (HDLCD_REG_H_BACK_PORCH, Horizontal->BackPorch);
+ MmioWrite32 (HDLCD_REG_H_DATA, Horizontal->Resolution - 1);
+ MmioWrite32 (HDLCD_REG_H_FRONT_PORCH, Horizontal->FrontPorch);
+
+ // Enable the controller
+ MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_ENABLE);
+
+ return EFI_SUCCESS;
+}
+
+/** De-initializes the display.
+**/
+VOID
+LcdShutdown (
+ VOID
+ )
+{
+ // Disable the controller
+ MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
+}
+
+/** Check for presence of HDLCD.
+
+ @retval EFI_SUCCESS Returns success if platform implements a HDLCD
+ controller.
+ @retval EFI_NOT_FOUND HDLCD display controller not found on the
+ platform.
+**/
+EFI_STATUS
+LcdIdentify (
+ VOID
+ )
+{
+ if ((MmioRead32 (HDLCD_REG_VERSION) >> 16) == HDLCD_PRODUCT_ID) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h
new file mode 100644
index 000000000..ca5c6676c
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h
@@ -0,0 +1,84 @@
+/** @file
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef HDLCD_H_
+#define HDLCD_H_
+
+// HDLCD Controller Register Offsets
+#define HDLCD_REG_VERSION ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x000)
+#define HDLCD_REG_INT_RAWSTAT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x010)
+#define HDLCD_REG_INT_CLEAR ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x014)
+#define HDLCD_REG_INT_MASK ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x018)
+#define HDLCD_REG_INT_STATUS ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x01C)
+#define HDLCD_REG_FB_BASE ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x100)
+#define HDLCD_REG_FB_LINE_LENGTH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x104)
+#define HDLCD_REG_FB_LINE_COUNT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x108)
+#define HDLCD_REG_FB_LINE_PITCH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x10C)
+#define HDLCD_REG_BUS_OPTIONS ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x110)
+#define HDLCD_REG_V_SYNC ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x200)
+#define HDLCD_REG_V_BACK_PORCH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x204)
+#define HDLCD_REG_V_DATA ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x208)
+#define HDLCD_REG_V_FRONT_PORCH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x20C)
+#define HDLCD_REG_H_SYNC ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x210)
+#define HDLCD_REG_H_BACK_PORCH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x214)
+#define HDLCD_REG_H_DATA ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x218)
+#define HDLCD_REG_H_FRONT_PORCH ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x21C)
+#define HDLCD_REG_POLARITIES ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x220)
+#define HDLCD_REG_COMMAND ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x230)
+#define HDLCD_REG_PIXEL_FORMAT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x240)
+#define HDLCD_REG_RED_SELECT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x244)
+#define HDLCD_REG_GREEN_SELECT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x248)
+#define HDLCD_REG_BLUE_SELECT ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x24C)
+
+// HDLCD Values of registers
+
+// HDLCD Interrupt mask, clear and status register
+#define HDLCD_DMA_END BIT0 /* DMA has finished reading a frame */
+#define HDLCD_BUS_ERROR BIT1 /* DMA bus error */
+#define HDLCD_SYNC BIT2 /* Vertical sync */
+#define HDLCD_UNDERRUN BIT3 /* No Data available while DATAEN active */
+
+// CLCD_CONTROL Control register
+#define HDLCD_DISABLE 0
+#define HDLCD_ENABLE BIT0
+
+// Bus Options
+#define HDLCD_BURST_1 BIT0
+#define HDLCD_BURST_2 BIT1
+#define HDLCD_BURST_4 BIT2
+#define HDLCD_BURST_8 BIT3
+#define HDLCD_BURST_16 BIT4
+
+// Polarities - HIGH
+#define HDLCD_VSYNC_HIGH BIT0
+#define HDLCD_HSYNC_HIGH BIT1
+#define HDLCD_DATEN_HIGH BIT2
+#define HDLCD_DATA_HIGH BIT3
+#define HDLCD_PXCLK_HIGH BIT4
+// Polarities - LOW (for completion and for ease of understanding the hardware settings)
+#define HDLCD_VSYNC_LOW 0
+#define HDLCD_HSYNC_LOW 0
+#define HDLCD_DATEN_LOW 0
+#define HDLCD_DATA_LOW 0
+#define HDLCD_PXCLK_LOW 0
+
+// Default polarities
+#define HDLCD_DEFAULT_POLARITIES (HDLCD_PXCLK_LOW | HDLCD_DATA_HIGH | \
+ HDLCD_DATEN_HIGH | HDLCD_HSYNC_LOW | \
+ HDLCD_VSYNC_HIGH)
+
+// Pixel Format
+#define HDLCD_LITTLE_ENDIAN (0 << 31)
+#define HDLCD_BIG_ENDIAN (1 << 31)
+
+// Number of bytes per pixel
+#define HDLCD_4BYTES_PER_PIXEL ((4 - 1) << 3)
+
+#define HDLCD_PRODUCT_ID 0x1CDC
+
+#endif /* HDLCD_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf
new file mode 100644
index 000000000..bc80e1ade
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf
@@ -0,0 +1,39 @@
+#/** @file
+#
+# Component description file for HDLCD module
+#
+# Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HdLcd
+ FILE_GUID = ce660500-824d-11e0-ac72-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LcdHwLib
+
+[Sources.common]
+ HdLcd.h
+ HdLcd.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmPkg/ArmPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ ArmLib
+ UefiLib
+ BaseLib
+ DebugLib
+ IoLib
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdArmHdLcdBase
+ gArmPlatformTokenSpaceGuid.PcdArmHdLcdSwapBlueRedSelect
+
diff --git a/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.c b/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.c
new file mode 100644
index 000000000..ca4887199
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.c
@@ -0,0 +1,69 @@
+/** @file
+
+ Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/LcdPlatformLib.h>
+
+/**
+ Check for presence of display
+
+ @retval EFI_SUCCESS Platform implements display.
+ @retval EFI_NOT_FOUND Display not found on the platform.
+
+**/
+EFI_STATUS
+LcdIdentify (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize display.
+
+ @param FrameBaseAddress Address of the frame buffer.
+ @retval EFI_SUCCESS Display initialization success.
+ @retval !(EFI_SUCCESS) Display initialization failure.
+
+**/
+EFI_STATUS
+LcdInitialize (
+ EFI_PHYSICAL_ADDRESS FrameBaseAddress
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Set requested mode of the display.
+
+ @param ModeNumber Display mode number.
+ @retval EFI_SUCCESS Display set mode success.
+ @retval EFI_DEVICE_ERROR If mode not found/supported.
+
+**/
+EFI_STATUS
+LcdSetMode (
+ IN UINT32 ModeNumber
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ De-initializes the display.
+**/
+VOID
+LcdShutdown (
+ VOID
+ )
+{
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf b/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf
new file mode 100644
index 000000000..82e10fa69
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf
@@ -0,0 +1,22 @@
+#/** @file
+#
+# Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = LcdHwNullLib
+ FILE_GUID = bb1fde98-1de2-410e-8850-fdcb8e67ebc0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LcdHwLib
+
+[Sources]
+ LcdHwNullLib.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
diff --git a/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.c b/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.c
new file mode 100644
index 000000000..dca3cf706
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.c
@@ -0,0 +1,145 @@
+/** @file
+
+ Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+ Copyright (c) 2018, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/LcdPlatformLib.h>
+
+/** Platform related initialization function.
+
+ @param[in] Handle Handle to the LCD device instance.
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+**/
+EFI_STATUS
+LcdPlatformInitializeDisplay (
+ IN EFI_HANDLE Handle
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/** Allocate VRAM memory in DRAM for the framebuffer
+ (unless it is reserved already).
+
+ The allocated address can be used to set the framebuffer.
+
+ @param[out] VramBaseAddress A pointer to the framebuffer address.
+ @param[out] VramSize A pointer to the size of the frame
+ buffer in bytes
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+**/
+EFI_STATUS
+LcdPlatformGetVram (
+ OUT EFI_PHYSICAL_ADDRESS* VramBaseAddress,
+ OUT UINTN* VramSize
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/** Return total number of modes supported.
+
+ Note: Valid mode numbers are 0 to MaxMode - 1
+ See Section 12.9 of the UEFI Specification 2.7
+
+ @retval UINT32 Zero number of modes supported
+ in a NULL library implementation.
+**/
+UINT32
+LcdPlatformGetMaxMode (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+ return 0;
+}
+
+/** Set the requested display mode.
+
+ @param[in] ModeNumber Mode Number.
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+**/
+EFI_STATUS
+LcdPlatformSetMode (
+ IN UINT32 ModeNumber
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/** Return information for the requested mode number.
+
+ @param[in] ModeNumber Mode Number.
+ @param[out] Info Pointer for returned mode information
+ (on success).
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+
+**/
+EFI_STATUS
+LcdPlatformQueryMode (
+ IN UINT32 ModeNumber,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/** Return display timing information for the requested mode number.
+
+ @param[in] ModeNumber Mode Number.
+
+ @param[out] HRes Pointer to horizontal resolution.
+ @param[out] HSync Pointer to horizontal sync width.
+ @param[out] HBackPorch Pointer to horizontal back porch.
+ @param[out] HFrontPorch Pointer to horizontal front porch.
+ @param[out] VRes Pointer to vertical resolution.
+ @param[out] VSync Pointer to vertical sync width.
+ @param[out] VBackPorch Pointer to vertical back porch.
+ @param[out] VFrontPorch Pointer to vertical front porch.
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+**/
+EFI_STATUS
+LcdPlatformGetTimings (
+ IN UINT32 ModeNumber,
+ OUT SCAN_TIMINGS **Horizontal,
+ OUT SCAN_TIMINGS **Vertical
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/** Return bits per pixel information for a mode number.
+
+ @param[in] ModeNumber Mode Number.
+
+ @param[out] Bpp Pointer to value bits per pixel information.
+
+ @retval EFI_UNSUPPORTED Interface is not supported.
+
+**/
+EFI_STATUS
+LcdPlatformGetBpp (
+ IN UINT32 ModeNumber,
+ OUT LCD_BPP* Bpp
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf b/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf
new file mode 100644
index 000000000..558570816
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf
@@ -0,0 +1,22 @@
+#/** @file
+#
+# Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = LcdPlatformNullLib
+ FILE_GUID = b78d02bb-d0b5-4389-bc7f-b39ee846c784
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LcdPlatformLib
+
+[Sources]
+ LcdPlatformNullLib.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
diff --git a/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.c b/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.c
new file mode 100644
index 000000000..1237f9382
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.c
@@ -0,0 +1,28 @@
+/** @file
+
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#include <Library/NorFlashPlatformLib.h>
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ )
+{
+ *NorFlashDescriptions = NULL;
+ *Count = 0;
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf b/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf
new file mode 100644
index 000000000..3a2d5a171
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf
@@ -0,0 +1,24 @@
+#/** @file
+#
+# Component description file for NorFlashPlatformNullLib module
+#
+# Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NorFlashPlatformNullLib
+ FILE_GUID = 29b733ad-d066-4df6-8a89-b9df1beb818a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashPlatformLib
+
+[Sources.common]
+ NorFlashPlatformNullLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c b/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c
new file mode 100644
index 000000000..a552e6ab9
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c
@@ -0,0 +1,237 @@
+/** @file
+ Serial I/O Port library functions with no library constructor/destructor
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012 - 2016, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PL011UartClockLib.h>
+#include <Library/PL011UartLib.h>
+#include <Library/SerialPortLib.h>
+
+/** Initialise the serial device hardware with default settings.
+
+ @retval RETURN_SUCCESS The serial device was initialised.
+ @retval RETURN_INVALID_PARAMETER One or more of the default settings
+ has an unsupported value.
+ **/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINT64 BaudRate;
+ UINT32 ReceiveFifoDepth;
+ EFI_PARITY_TYPE Parity;
+ UINT8 DataBits;
+ EFI_STOP_BITS_TYPE StopBits;
+
+ BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);
+ ReceiveFifoDepth = 0; // Use default FIFO depth
+ Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
+ DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
+ StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);
+
+ return PL011UartInitializePort (
+ (UINTN)PcdGet64 (PcdSerialRegisterBase),
+ PL011UartClockGetFreq(),
+ &BaudRate,
+ &ReceiveFifoDepth,
+ &Parity,
+ &DataBits,
+ &StopBits
+ );
+}
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ return PL011UartWrite ((UINTN)PcdGet64 (PcdSerialRegisterBase), Buffer, NumberOfBytes);
+}
+
+/**
+ Read data from serial device and save the data in buffer.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ return PL011UartRead ((UINTN)PcdGet64 (PcdSerialRegisterBase), Buffer, NumberOfBytes);
+}
+
+/**
+ Check to see if any data is available to be read from the debug device.
+
+ @retval TRUE At least one byte of data is available to be read
+ @retval FALSE No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ return PL011UartPoll ((UINTN)PcdGet64 (PcdSerialRegisterBase));
+}
+/**
+ Set new attributes to PL011.
+
+ @param BaudRate The baud rate of the serial device. If the
+ baud rate is not supported, the speed will
+ be reduced down to the nearest supported one
+ and the variable's value will be updated
+ accordingly.
+ @param ReceiveFifoDepth The number of characters the device will
+ buffer on input. If the specified value is
+ not supported, the variable's value will
+ be reduced down to the nearest supported one.
+ @param Timeout If applicable, the number of microseconds the
+ device will wait before timing out a Read or
+ a Write operation.
+ @param Parity If applicable, this is the EFI_PARITY_TYPE
+ that is computed or checked as each character
+ is transmitted or received. If the device
+ does not support parity, the value is the
+ default parity value.
+ @param DataBits The number of data bits in each character
+ @param StopBits If applicable, the EFI_STOP_BITS_TYPE number
+ of stop bits per character. If the device
+ does not support stop bits, the value is the
+ default stop bit value.
+
+ @retval EFI_SUCCESS All attributes were set correctly.
+ @retval EFI_INVALID_PARAMETERS One or more attributes has an unsupported
+ value.
+
+**/
+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 PL011UartInitializePort (
+ (UINTN)PcdGet64 (PcdSerialRegisterBase),
+ PL011UartClockGetFreq(),
+ BaudRate,
+ ReceiveFifoDepth,
+ Parity,
+ DataBits,
+ StopBits
+ );
+}
+
+/**
+
+ Assert or deassert the control signals on a serial port.
+ The following control signals are set according their bit settings :
+ . Request to Send
+ . Data Terminal Ready
+
+ @param[in] Control The following bits are taken into account :
+ . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
+ "Request To Send" control signal if this bit is
+ equal to one/zero.
+ . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
+ the "Data Terminal Ready" control signal if this
+ bit is equal to one/zero.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
+ the hardware loopback if this bit is equal to
+ one/zero.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
+ disable the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals.
+
+ @retval RETURN_SUCCESS The new control bits were set on the device.
+ @retval RETURN_UNSUPPORTED The device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortSetControl (
+ IN UINT32 Control
+ )
+{
+ return PL011UartSetControl ((UINTN)PcdGet64 (PcdSerialRegisterBase), Control);
+}
+
+/**
+
+ Retrieve the status of the control bits on a serial device.
+
+ @param[out] Control Status of the control bits on a serial device :
+
+ . EFI_SERIAL_DATA_CLEAR_TO_SEND,
+ EFI_SERIAL_DATA_SET_READY,
+ EFI_SERIAL_RING_INDICATE,
+ EFI_SERIAL_CARRIER_DETECT,
+ EFI_SERIAL_REQUEST_TO_SEND,
+ EFI_SERIAL_DATA_TERMINAL_READY
+ are all related to the DTE (Data Terminal Equipment)
+ and DCE (Data Communication Equipment) modes of
+ operation of the serial device.
+ . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
+ receive buffer is empty, 0 otherwise.
+ . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
+ transmit buffer is empty, 0 otherwise.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
+ the hardware loopback is enabled (the output feeds
+ the receive buffer), 0 otherwise.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one
+ if a loopback is accomplished by software, else 0.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
+ one if the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals is
+ enabled, 0 otherwise.
+
+ @retval RETURN_SUCCESS The control bits were read from the device.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortGetControl (
+ OUT UINT32 *Control
+ )
+{
+ return PL011UartGetControl ((UINTN)PcdGet64 (PcdSerialRegisterBase), Control);
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf b/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
new file mode 100644
index 000000000..b6b87f32a
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
@@ -0,0 +1,41 @@
+#/** @file
+#
+# Component description file for PL011SerialPortLib module
+#
+# Copyright (c) 2011-2016, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL011SerialPortLib
+ FILE_GUID = 8ecefc8f-a2c4-4091-b80f-20f7aeb0567f
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+[Sources.common]
+ PL011SerialPortLib.c
+
+[LibraryClasses]
+ PL011UartClockLib
+ PL011UartLib
+ PcdLib
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+ gArmPlatformTokenSpaceGuid.PL011UartClkInHz
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.c b/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.c
new file mode 100644
index 000000000..669be9daf
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.c
@@ -0,0 +1,23 @@
+/** @file
+*
+* Copyright 2018 NXP
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Base.h>
+
+/**
+ Return clock in for PL011 Uart IP
+
+ @return Pcd PL011UartClkInHz
+**/
+UINT32
+EFIAPI
+PL011UartClockGetFreq (
+ VOID
+ )
+{
+ return FixedPcdGet32 (PL011UartClkInHz);
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf b/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
new file mode 100644
index 000000000..c45359eb4
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
@@ -0,0 +1,24 @@
+#/* @file
+# Copyright 2018 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = BasePL011UartClockLib
+ FILE_GUID = af8fef24-afbb-472a-b8b7-13101a79703c
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL011UartClockLib
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+
+[Sources.common]
+ PL011UartClockLib.c
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PL011UartClkInHz
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011Uart.h b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011Uart.h
new file mode 100644
index 000000000..21b2acf9d
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011Uart.h
@@ -0,0 +1,114 @@
+/** @file
+*
+* Copyright (c) 2011-2016, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef __PL011_UART_H__
+#define __PL011_UART_H__
+
+#define PL011_VARIANT_ZTE 1
+
+// PL011 Registers
+#if FixedPcdGet8 (PL011UartRegOffsetVariant) == PL011_VARIANT_ZTE
+#define UARTDR 0x004
+#define UARTRSR 0x010
+#define UARTECR 0x010
+#define UARTFR 0x014
+#define UARTIBRD 0x024
+#define UARTFBRD 0x028
+#define UARTLCR_H 0x030
+#define UARTCR 0x034
+#define UARTIFLS 0x038
+#define UARTIMSC 0x040
+#define UARTRIS 0x044
+#define UARTMIS 0x048
+#define UARTICR 0x04c
+#define UARTDMACR 0x050
+#else
+#define UARTDR 0x000
+#define UARTRSR 0x004
+#define UARTECR 0x004
+#define UARTFR 0x018
+#define UARTILPR 0x020
+#define UARTIBRD 0x024
+#define UARTFBRD 0x028
+#define UARTLCR_H 0x02C
+#define UARTCR 0x030
+#define UARTIFLS 0x034
+#define UARTIMSC 0x038
+#define UARTRIS 0x03C
+#define UARTMIS 0x040
+#define UARTICR 0x044
+#define UARTDMACR 0x048
+#endif
+
+#define UARTPID0 0xFE0
+#define UARTPID1 0xFE4
+#define UARTPID2 0xFE8
+#define UARTPID3 0xFEC
+
+// Data status bits
+#define UART_DATA_ERROR_MASK 0x0F00
+
+// Status reg bits
+#define UART_STATUS_ERROR_MASK 0x0F
+
+// Flag reg bits
+#if FixedPcdGet8 (PL011UartRegOffsetVariant) == PL011_VARIANT_ZTE
+#define PL011_UARTFR_RI (1 << 0) // Ring indicator
+#define PL011_UARTFR_TXFE (1 << 7) // Transmit FIFO empty
+#define PL011_UARTFR_RXFF (1 << 6) // Receive FIFO full
+#define PL011_UARTFR_TXFF (1 << 5) // Transmit FIFO full
+#define PL011_UARTFR_RXFE (1 << 4) // Receive FIFO empty
+#define PL011_UARTFR_BUSY (1 << 8) // UART busy
+#define PL011_UARTFR_DCD (1 << 2) // Data carrier detect
+#define PL011_UARTFR_DSR (1 << 3) // Data set ready
+#define PL011_UARTFR_CTS (1 << 1) // Clear to send
+#else
+#define PL011_UARTFR_RI (1 << 8) // Ring indicator
+#define PL011_UARTFR_TXFE (1 << 7) // Transmit FIFO empty
+#define PL011_UARTFR_RXFF (1 << 6) // Receive FIFO full
+#define PL011_UARTFR_TXFF (1 << 5) // Transmit FIFO full
+#define PL011_UARTFR_RXFE (1 << 4) // Receive FIFO empty
+#define PL011_UARTFR_BUSY (1 << 3) // UART busy
+#define PL011_UARTFR_DCD (1 << 2) // Data carrier detect
+#define PL011_UARTFR_DSR (1 << 1) // Data set ready
+#define PL011_UARTFR_CTS (1 << 0) // Clear to send
+#endif
+
+// Flag reg bits - alternative names
+#define UART_TX_EMPTY_FLAG_MASK PL011_UARTFR_TXFE
+#define UART_RX_FULL_FLAG_MASK PL011_UARTFR_RXFF
+#define UART_TX_FULL_FLAG_MASK PL011_UARTFR_TXFF
+#define UART_RX_EMPTY_FLAG_MASK PL011_UARTFR_RXFE
+#define UART_BUSY_FLAG_MASK PL011_UARTFR_BUSY
+
+// Control reg bits
+#define PL011_UARTCR_CTSEN (1 << 15) // CTS hardware flow control enable
+#define PL011_UARTCR_RTSEN (1 << 14) // RTS hardware flow control enable
+#define PL011_UARTCR_RTS (1 << 11) // Request to send
+#define PL011_UARTCR_DTR (1 << 10) // Data transmit ready.
+#define PL011_UARTCR_RXE (1 << 9) // Receive enable
+#define PL011_UARTCR_TXE (1 << 8) // Transmit enable
+#define PL011_UARTCR_LBE (1 << 7) // Loopback enable
+#define PL011_UARTCR_UARTEN (1 << 0) // UART Enable
+
+// Line Control Register Bits
+#define PL011_UARTLCR_H_SPS (1 << 7) // Stick parity select
+#define PL011_UARTLCR_H_WLEN_8 (3 << 5)
+#define PL011_UARTLCR_H_WLEN_7 (2 << 5)
+#define PL011_UARTLCR_H_WLEN_6 (1 << 5)
+#define PL011_UARTLCR_H_WLEN_5 (0 << 5)
+#define PL011_UARTLCR_H_FEN (1 << 4) // FIFOs Enable
+#define PL011_UARTLCR_H_STP2 (1 << 3) // Two stop bits select
+#define PL011_UARTLCR_H_EPS (1 << 2) // Even parity select
+#define PL011_UARTLCR_H_PEN (1 << 1) // Parity Enable
+#define PL011_UARTLCR_H_BRK (1 << 0) // Send break
+
+#define PL011_UARTPID2_VER(X) (((X) >> 4) & 0xF)
+#define PL011_VER_R1P4 0x2
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.c b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.c
new file mode 100644
index 000000000..f1015b1fc
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.c
@@ -0,0 +1,472 @@
+/** @file
+ Serial I/O Port library functions with no library constructor/destructor
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/SerialIo.h>
+
+#include "PL011Uart.h"
+
+#define FRACTION_PART_SIZE_IN_BITS 6
+#define FRACTION_PART_MASK ((1 << FRACTION_PART_SIZE_IN_BITS) - 1)
+
+//
+// EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE is the only
+// control bit that is not supported.
+//
+STATIC CONST UINT32 mInvalidControlBits = EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
+
+/**
+
+ Initialise the serial port to the specified settings.
+ The serial port is re-configured only if the specified settings
+ are different from the current settings.
+ All unspecified settings will be set to the default values.
+
+ @param UartBase The base address of the serial device.
+ @param UartClkInHz The clock in Hz for the serial device.
+ Ignored if the PCD PL011UartInteger is not 0
+ @param BaudRate The baud rate of the serial device. If the
+ baud rate is not supported, the speed will be
+ reduced to the nearest supported one and the
+ variable's value will be updated accordingly.
+ @param ReceiveFifoDepth The number of characters the device will
+ buffer on input. Value of 0 will use the
+ device's default FIFO depth.
+ @param Parity If applicable, this is the EFI_PARITY_TYPE
+ that is computed or checked as each character
+ is transmitted or received. If the device
+ does not support parity, the value is the
+ default parity value.
+ @param DataBits The number of data bits in each character.
+ @param StopBits If applicable, the EFI_STOP_BITS_TYPE number
+ of stop bits per character.
+ If the device does not support stop bits, the
+ value is the default stop bit value.
+
+ @retval RETURN_SUCCESS All attributes were set correctly on the
+ serial device.
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an
+ unsupported value.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartInitializePort (
+ IN UINTN UartBase,
+ IN UINT32 UartClkInHz,
+ IN OUT UINT64 *BaudRate,
+ IN OUT UINT32 *ReceiveFifoDepth,
+ IN OUT EFI_PARITY_TYPE *Parity,
+ IN OUT UINT8 *DataBits,
+ IN OUT EFI_STOP_BITS_TYPE *StopBits
+ )
+{
+ UINT32 LineControl;
+ UINT32 Divisor;
+ UINT32 Integer;
+ UINT32 Fractional;
+ UINT32 HardwareFifoDepth;
+ UINT32 UartPid2;
+
+ HardwareFifoDepth = FixedPcdGet16 (PcdUartDefaultReceiveFifoDepth);
+ if (HardwareFifoDepth == 0) {
+ UartPid2 = MmioRead32 (UartBase + UARTPID2);
+ HardwareFifoDepth = (PL011_UARTPID2_VER (UartPid2) > PL011_VER_R1P4) ? 32 : 16;
+ }
+
+ // The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can accept
+ // 1 char buffer as the minimum FIFO size. Because everything can be rounded
+ // down, there is no maximum FIFO size.
+ if ((*ReceiveFifoDepth == 0) || (*ReceiveFifoDepth >= HardwareFifoDepth)) {
+ // Enable FIFO
+ LineControl = PL011_UARTLCR_H_FEN;
+ *ReceiveFifoDepth = HardwareFifoDepth;
+ } else {
+ // Disable FIFO
+ LineControl = 0;
+ // Nothing else to do. 1 byte FIFO is default.
+ *ReceiveFifoDepth = 1;
+ }
+
+ //
+ // Parity
+ //
+ switch (*Parity) {
+ case DefaultParity:
+ *Parity = NoParity;
+ case NoParity:
+ // Nothing to do. Parity is disabled by default.
+ break;
+ case EvenParity:
+ LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_EPS);
+ break;
+ case OddParity:
+ LineControl |= PL011_UARTLCR_H_PEN;
+ break;
+ case MarkParity:
+ LineControl |= ( PL011_UARTLCR_H_PEN \
+ | PL011_UARTLCR_H_SPS \
+ | PL011_UARTLCR_H_EPS);
+ break;
+ case SpaceParity:
+ LineControl |= (PL011_UARTLCR_H_PEN | PL011_UARTLCR_H_SPS);
+ break;
+ default:
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ //
+ // Data Bits
+ //
+ switch (*DataBits) {
+ case 0:
+ *DataBits = 8;
+ case 8:
+ LineControl |= PL011_UARTLCR_H_WLEN_8;
+ break;
+ case 7:
+ LineControl |= PL011_UARTLCR_H_WLEN_7;
+ break;
+ case 6:
+ LineControl |= PL011_UARTLCR_H_WLEN_6;
+ break;
+ case 5:
+ LineControl |= PL011_UARTLCR_H_WLEN_5;
+ break;
+ default:
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ //
+ // Stop Bits
+ //
+ switch (*StopBits) {
+ case DefaultStopBits:
+ *StopBits = OneStopBit;
+ case OneStopBit:
+ // Nothing to do. One stop bit is enabled by default.
+ break;
+ case TwoStopBits:
+ LineControl |= PL011_UARTLCR_H_STP2;
+ break;
+ case OneFiveStopBits:
+ // Only 1 or 2 stop bits are supported
+ default:
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ // Don't send the LineControl value to the PL011 yet,
+ // wait until after the Baud Rate setting.
+ // This ensures we do not mess up the UART settings halfway through
+ // in the rare case when there is an error with the Baud Rate.
+
+ //
+ // Baud Rate
+ //
+
+ // If PL011 Integer value has been defined then always ignore the BAUD rate
+ if (FixedPcdGet32 (PL011UartInteger) != 0) {
+ Integer = FixedPcdGet32 (PL011UartInteger);
+ Fractional = FixedPcdGet32 (PL011UartFractional);
+ } else {
+ // If BAUD rate is zero then replace it with the system default value
+ if (*BaudRate == 0) {
+ *BaudRate = FixedPcdGet32 (PcdSerialBaudRate);
+ if (*BaudRate == 0) {
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ if (0 == UartClkInHz) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Divisor = (UartClkInHz * 4) / *BaudRate;
+ Integer = Divisor >> FRACTION_PART_SIZE_IN_BITS;
+ Fractional = Divisor & FRACTION_PART_MASK;
+ }
+
+ //
+ // If PL011 is already initialized, check the current settings
+ // and re-initialize only if the settings are different.
+ //
+ if (((MmioRead32 (UartBase + UARTCR) & PL011_UARTCR_UARTEN) != 0) &&
+ (MmioRead32 (UartBase + UARTLCR_H) == LineControl) &&
+ (MmioRead32 (UartBase + UARTIBRD) == Integer) &&
+ (MmioRead32 (UartBase + UARTFBRD) == Fractional)) {
+ // Nothing to do - already initialized with correct attributes
+ return RETURN_SUCCESS;
+ }
+
+ // Wait for the end of transmission
+ while ((MmioRead32 (UartBase + UARTFR) & PL011_UARTFR_TXFE) == 0);
+
+ // Disable UART: "The UARTLCR_H, UARTIBRD, and UARTFBRD registers must not be changed
+ // when the UART is enabled"
+ MmioWrite32 (UartBase + UARTCR, 0);
+
+ // Set Baud Rate Registers
+ MmioWrite32 (UartBase + UARTIBRD, Integer);
+ MmioWrite32 (UartBase + UARTFBRD, Fractional);
+
+ // No parity, 1 stop, no fifo, 8 data bits
+ MmioWrite32 (UartBase + UARTLCR_H, LineControl);
+
+ // Clear any pending errors
+ MmioWrite32 (UartBase + UARTECR, 0);
+
+ // Enable Tx, Rx, and UART overall
+ MmioWrite32 (UartBase + UARTCR,
+ PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+
+ Assert or deassert the control signals on a serial port.
+ The following control signals are set according their bit settings :
+ . Request to Send
+ . Data Terminal Ready
+
+ @param[in] UartBase UART registers base address
+ @param[in] Control The following bits are taken into account :
+ . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
+ "Request To Send" control signal if this bit is
+ equal to one/zero.
+ . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
+ the "Data Terminal Ready" control signal if this
+ bit is equal to one/zero.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
+ the hardware loopback if this bit is equal to
+ one/zero.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
+ disable the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals.
+
+ @retval RETURN_SUCCESS The new control bits were set on the device.
+ @retval RETURN_UNSUPPORTED The device does not support this operation.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartSetControl (
+ IN UINTN UartBase,
+ IN UINT32 Control
+ )
+{
+ UINT32 Bits;
+
+ if (Control & (mInvalidControlBits)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ Bits = MmioRead32 (UartBase + UARTCR);
+
+ if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
+ Bits |= PL011_UARTCR_RTS;
+ } else {
+ Bits &= ~PL011_UARTCR_RTS;
+ }
+
+ if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
+ Bits |= PL011_UARTCR_DTR;
+ } else {
+ Bits &= ~PL011_UARTCR_DTR;
+ }
+
+ if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
+ Bits |= PL011_UARTCR_LBE;
+ } else {
+ Bits &= ~PL011_UARTCR_LBE;
+ }
+
+ if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
+ Bits |= (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
+ } else {
+ Bits &= ~(PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN);
+ }
+
+ MmioWrite32 (UartBase + UARTCR, Bits);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+
+ Retrieve the status of the control bits on a serial device.
+
+ @param[in] UartBase UART registers base address
+ @param[out] Control Status of the control bits on a serial device :
+
+ . EFI_SERIAL_DATA_CLEAR_TO_SEND,
+ EFI_SERIAL_DATA_SET_READY,
+ EFI_SERIAL_RING_INDICATE,
+ EFI_SERIAL_CARRIER_DETECT,
+ EFI_SERIAL_REQUEST_TO_SEND,
+ EFI_SERIAL_DATA_TERMINAL_READY
+ are all related to the DTE (Data Terminal Equipment)
+ and DCE (Data Communication Equipment) modes of
+ operation of the serial device.
+ . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
+ receive buffer is empty, 0 otherwise.
+ . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
+ transmit buffer is empty, 0 otherwise.
+ . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
+ the hardware loopback is enabled (the output feeds the
+ receive buffer), 0 otherwise.
+ . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
+ a loopback is accomplished by software, 0 otherwise.
+ . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
+ one if the hardware flow control based on CTS (Clear
+ To Send) and RTS (Ready To Send) control signals is
+ enabled, 0 otherwise.
+
+ @retval RETURN_SUCCESS The control bits were read from the serial device.
+
+**/
+RETURN_STATUS
+EFIAPI
+PL011UartGetControl (
+ IN UINTN UartBase,
+ OUT UINT32 *Control
+ )
+{
+ UINT32 FlagRegister;
+ UINT32 ControlRegister;
+
+
+ FlagRegister = MmioRead32 (UartBase + UARTFR);
+ ControlRegister = MmioRead32 (UartBase + UARTCR);
+
+ *Control = 0;
+
+ if ((FlagRegister & PL011_UARTFR_CTS) == PL011_UARTFR_CTS) {
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;
+ }
+
+ if ((FlagRegister & PL011_UARTFR_DSR) == PL011_UARTFR_DSR) {
+ *Control |= EFI_SERIAL_DATA_SET_READY;
+ }
+
+ if ((FlagRegister & PL011_UARTFR_RI) == PL011_UARTFR_RI) {
+ *Control |= EFI_SERIAL_RING_INDICATE;
+ }
+
+ if ((FlagRegister & PL011_UARTFR_DCD) == PL011_UARTFR_DCD) {
+ *Control |= EFI_SERIAL_CARRIER_DETECT;
+ }
+
+ if ((ControlRegister & PL011_UARTCR_RTS) == PL011_UARTCR_RTS) {
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;
+ }
+
+ if ((ControlRegister & PL011_UARTCR_DTR) == PL011_UARTCR_DTR) {
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
+ }
+
+ if ((FlagRegister & PL011_UARTFR_RXFE) == PL011_UARTFR_RXFE) {
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
+ }
+
+ if ((FlagRegister & PL011_UARTFR_TXFE) == PL011_UARTFR_TXFE) {
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+
+ if ((ControlRegister & (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN))
+ == (PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN)) {
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+
+ if ((ControlRegister & PL011_UARTCR_LBE) == PL011_UARTCR_LBE) {
+ *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+PL011UartWrite (
+ IN UINTN UartBase,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINT8* CONST Final = &Buffer[NumberOfBytes];
+
+ while (Buffer < Final) {
+ // Wait until UART able to accept another char
+ while ((MmioRead32 (UartBase + UARTFR) & UART_TX_FULL_FLAG_MASK));
+
+ MmioWrite8 (UartBase + UARTDR, *Buffer++);
+ }
+
+ return NumberOfBytes;
+}
+
+/**
+ Read data from serial device and save the data in buffer.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+PL011UartRead (
+ IN UINTN UartBase,
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINTN Count;
+
+ for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
+ while ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) != 0);
+ *Buffer = MmioRead8 (UartBase + UARTDR);
+ }
+
+ return NumberOfBytes;
+}
+
+/**
+ Check to see if any data is available to be read from the debug device.
+
+ @retval TRUE At least one byte of data is available to be read
+ @retval FALSE No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+PL011UartPoll (
+ IN UINTN UartBase
+ )
+{
+ return ((MmioRead32 (UartBase + UARTFR) & UART_RX_EMPTY_FLAG_MASK) == 0);
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
new file mode 100644
index 000000000..e3da50798
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
@@ -0,0 +1,38 @@
+#/** @file
+#
+# Component description file for PL011Uart module
+#
+# Copyright (c) 2011-2016, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL011UartLib
+ FILE_GUID = 6a2c5714-8910-44f0-861f-804abc18ce39
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL011UartLib
+
+[Sources.common]
+ PL011Uart.h
+ PL011UartLib.c
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultReceiveFifoDepth
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
+
+ gArmPlatformTokenSpaceGuid.PL011UartInteger
+ gArmPlatformTokenSpaceGuid.PL011UartFractional
+ gArmPlatformTokenSpaceGuid.PL011UartRegOffsetVariant
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClock.h b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClock.h
new file mode 100644
index 000000000..9f28ed7a2
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClock.h
@@ -0,0 +1,39 @@
+/** @file
+*
+* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#ifndef __PL031_REAL_TIME_CLOCK_H__
+#define __PL031_REAL_TIME_CLOCK_H__
+
+// PL031 Registers
+#define PL031_RTC_DR_DATA_REGISTER 0x000
+#define PL031_RTC_MR_MATCH_REGISTER 0x004
+#define PL031_RTC_LR_LOAD_REGISTER 0x008
+#define PL031_RTC_CR_CONTROL_REGISTER 0x00C
+#define PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER 0x010
+#define PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER 0x014
+#define PL031_RTC_MIS_MASKED_IRQ_STATUS_REGISTER 0x018
+#define PL031_RTC_ICR_IRQ_CLEAR_REGISTER 0x01C
+#define PL031_RTC_PERIPH_ID0 0xFE0
+#define PL031_RTC_PERIPH_ID1 0xFE4
+#define PL031_RTC_PERIPH_ID2 0xFE8
+#define PL031_RTC_PERIPH_ID3 0xFEC
+#define PL031_RTC_PCELL_ID0 0xFF0
+#define PL031_RTC_PCELL_ID1 0xFF4
+#define PL031_RTC_PCELL_ID2 0xFF8
+#define PL031_RTC_PCELL_ID3 0xFFC
+
+// PL031 Values
+#define PL031_RTC_ENABLED 0x00000001
+#define PL031_SET_IRQ_MASK 0x00000001
+#define PL031_IRQ_TRIGGERED 0x00000001
+#define PL031_CLEAR_IRQ 0x00000001
+
+#define PL031_COUNTS_PER_SECOND 1
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
new file mode 100644
index 000000000..75c95985d
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
@@ -0,0 +1,356 @@
+/** @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) 2019, Linaro Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+#include <Guid/GlobalVariable.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Library/TimeBaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/RealTimeClock.h>
+
+#include "PL031RealTimeClock.h"
+
+STATIC BOOLEAN mPL031Initialized = FALSE;
+STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;
+STATIC UINTN mPL031RtcBase;
+
+EFI_STATUS
+IdentifyPL031 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ // Check if this is a PrimeCell Peripheral
+ if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D)
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0)
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05)
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) {
+ Status = EFI_NOT_FOUND;
+ goto EXIT;
+ }
+
+ // Check if this PrimeCell Peripheral is the PL031 Real Time Clock
+ if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31)
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10)
+ || ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) {
+ Status = EFI_NOT_FOUND;
+ goto EXIT;
+ }
+
+ Status = EFI_SUCCESS;
+
+ EXIT:
+ return Status;
+}
+
+EFI_STATUS
+InitializePL031 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ // Prepare the hardware
+ Status = IdentifyPL031();
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ // Ensure interrupts are masked. We do not want RTC interrupts in UEFI
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != 0) {
+ MmioWrite32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, 0);
+ }
+
+ // Clear any existing interrupts
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {
+ MmioOr32 (mPL031RtcBase + PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);
+ }
+
+ // Start the clock counter
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {
+ MmioOr32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);
+ }
+
+ mPL031Initialized = 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;
+ UINT32 EpochSeconds;
+
+ // Ensure Time is a valid pointer
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize the hardware if not already done
+ if (!mPL031Initialized) {
+ Status = InitializePL031 ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ EpochSeconds = MmioRead32 (mPL031RtcBase + PL031_RTC_DR_DATA_REGISTER);
+
+ // Adjust for the correct time zone
+ // The timezone setting also reflects the DST setting of the clock
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ EpochSeconds += Time->TimeZone * SEC_PER_MIN;
+ } else 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) {
+ // PL031 runs at frequency 1Hz
+ Capabilities->Resolution = PL031_COUNTS_PER_SECOND;
+ // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000
+ Capabilities->Accuracy = (UINT32)PcdGet32 (PcdPL031RtcPpmAccuracy);
+ // FALSE: Setting the time does not clear the values below the resolution level
+ Capabilities->SetsToZero = FALSE;
+ }
+
+ 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;
+ UINT32 EpochSeconds;
+
+ // 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)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Initialize the hardware if not already done
+ if (!mPL031Initialized) {
+ Status = InitializePL031 ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ EpochSeconds = EfiTimeToEpoch (Time);
+
+ // Adjust for the correct time zone, i.e. convert to UTC time zone
+ // The timezone setting also reflects the DST setting of the clock
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ EpochSeconds -= Time->TimeZone * SEC_PER_MIN;
+ } else 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;
+ }
+
+ // Set the PL031
+ MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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**)&mPL031RtcBase);
+ 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;
+
+ // Initialize RTC Base Address
+ mPL031RtcBase = PcdGet32 (PcdPL031RtcBase);
+
+ // Declare the controller as EFI_MEMORY_RUNTIME
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mPL031RtcBase, SIZE_4KB,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gDS->SetMemorySpaceAttributes (mPL031RtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // 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/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
new file mode 100644
index 000000000..8224617f2
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
@@ -0,0 +1,45 @@
+#/** @file
+#
+# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL031RealTimeClockLib
+ FILE_GUID = 470DFB96-E205-4515-A75E-2E60F853E79D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib|DXE_RUNTIME_DRIVER
+
+[Sources.common]
+ PL031RealTimeClock.h
+ PL031RealTimeClockLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ UefiLib
+ DebugLib
+ PcdLib
+ DxeServicesTableLib
+ TimeBaseLib
+ UefiRuntimeLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+
+[Pcd]
+ gArmPlatformTokenSpaceGuid.PcdPL031RtcBase
+ gArmPlatformTokenSpaceGuid.PcdPL031RtcPpmAccuracy
+
+[Depex.common.DXE_RUNTIME_DRIVER]
+ gEfiCpuArchProtocolGuid
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c
new file mode 100644
index 000000000..05b6f8974
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c
@@ -0,0 +1,165 @@
+/** @file
+ This file contains the platform independent parts of PL111Lcd
+
+ Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/LcdHwLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "PL111Lcd.h"
+
+/** Check for presence of PL111.
+
+ @retval EFI_SUCCESS Returns success if platform implements a
+ PL111 controller.
+
+ @retval EFI_NOT_FOUND PL111 display controller not found the plaform.
+**/
+EFI_STATUS
+LcdIdentify (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL111\n",
+ PL111_REG_CLCD_PERIPH_ID_0));
+
+ // Check if this is a PL111
+ if (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_0) == PL111_CLCD_PERIPH_ID_0 &&
+ MmioRead8 (PL111_REG_CLCD_PERIPH_ID_1) == PL111_CLCD_PERIPH_ID_1 &&
+ (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_2) & 0xf) == PL111_CLCD_PERIPH_ID_2 &&
+ MmioRead8 (PL111_REG_CLCD_PERIPH_ID_3) == PL111_CLCD_PERIPH_ID_3 &&
+ MmioRead8 (PL111_REG_CLCD_P_CELL_ID_0) == PL111_CLCD_P_CELL_ID_0 &&
+ MmioRead8 (PL111_REG_CLCD_P_CELL_ID_1) == PL111_CLCD_P_CELL_ID_1 &&
+ MmioRead8 (PL111_REG_CLCD_P_CELL_ID_2) == PL111_CLCD_P_CELL_ID_2 &&
+ MmioRead8 (PL111_REG_CLCD_P_CELL_ID_3) == PL111_CLCD_P_CELL_ID_3) {
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+/** Initialize display.
+
+ @param[in] VramBaseAddress Address of the framebuffer.
+
+ @retval EFI_SUCCESS Initialization of display successful.
+**/
+EFI_STATUS
+LcdInitialize (
+ IN EFI_PHYSICAL_ADDRESS VramBaseAddress
+ )
+{
+ // Define start of the VRAM. This never changes for any graphics mode
+ MmioWrite32 (PL111_REG_LCD_UP_BASE, (UINT32)VramBaseAddress);
+ MmioWrite32 (PL111_REG_LCD_LP_BASE, 0); // We are not using a double buffer
+
+ // Disable all interrupts from the PL111
+ MmioWrite32 (PL111_REG_LCD_IMSC, 0);
+
+ return EFI_SUCCESS;
+}
+
+/** Set requested mode of the display.
+
+ @param[in] ModeNumbe Display mode number.
+
+ @retval EFI_SUCCESS Display mode set successfuly.
+ @retval !(EFI_SUCCESS) Other errors.
+**/
+EFI_STATUS
+LcdSetMode (
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status;
+ SCAN_TIMINGS *Horizontal;
+ SCAN_TIMINGS *Vertical;
+ UINT32 LcdControl;
+ LCD_BPP LcdBpp;
+
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
+
+ // Set the video mode timings and other relevant information
+ Status = LcdPlatformGetTimings (
+ ModeNumber,
+ &Horizontal,
+ &Vertical
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ ASSERT (Horizontal != NULL);
+ ASSERT (Vertical != NULL);
+
+ Status = LcdPlatformGetBpp (ModeNumber, &LcdBpp);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Get the pixel format information
+ Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Disable the CLCD_LcdEn bit
+ MmioAnd32 (PL111_REG_LCD_CONTROL, ~PL111_CTRL_LCD_EN);
+
+ // Set Timings
+ MmioWrite32 (
+ PL111_REG_LCD_TIMING_0,
+ HOR_AXIS_PANEL (
+ Horizontal->BackPorch,
+ Horizontal->FrontPorch,
+ Horizontal->Sync,
+ Horizontal->Resolution
+ )
+ );
+
+ MmioWrite32 (
+ PL111_REG_LCD_TIMING_1,
+ VER_AXIS_PANEL (
+ Vertical->BackPorch,
+ Vertical->FrontPorch,
+ Vertical->Sync,
+ Vertical->Resolution
+ )
+ );
+
+ MmioWrite32 (
+ PL111_REG_LCD_TIMING_2,
+ CLK_SIG_POLARITY (Horizontal->Resolution)
+ );
+
+ MmioWrite32 (PL111_REG_LCD_TIMING_3, 0);
+
+ // PL111_REG_LCD_CONTROL
+ LcdControl = PL111_CTRL_LCD_EN | PL111_CTRL_LCD_BPP (LcdBpp) |
+ PL111_CTRL_LCD_TFT | PL111_CTRL_LCD_PWR;
+ if (ModeInfo.PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+ LcdControl |= PL111_CTRL_BGR;
+ }
+ MmioWrite32 (PL111_REG_LCD_CONTROL, LcdControl);
+
+ return EFI_SUCCESS;
+}
+
+/** De-initializes the display.
+*/
+VOID
+LcdShutdown (
+ VOID
+ )
+{
+ // Disable the controller
+ MmioAnd32 (PL111_REG_LCD_CONTROL, ~PL111_CTRL_LCD_EN);
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h
new file mode 100644
index 000000000..fabf778c1
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h
@@ -0,0 +1,143 @@
+/** @file PL111Lcd.h
+
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef _PL111LCD_H__
+#define _PL111LCD_H__
+
+/**********************************************************************
+ *
+ * This header file contains all the bits of the PL111 that are
+ * platform independent.
+ *
+ **********************************************************************/
+
+// Controller Register Offsets
+#define PL111_REG_LCD_TIMING_0 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x000)
+#define PL111_REG_LCD_TIMING_1 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x004)
+#define PL111_REG_LCD_TIMING_2 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x008)
+#define PL111_REG_LCD_TIMING_3 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x00C)
+#define PL111_REG_LCD_UP_BASE ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x010)
+#define PL111_REG_LCD_LP_BASE ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x014)
+#define PL111_REG_LCD_CONTROL ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x018)
+#define PL111_REG_LCD_IMSC ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x01C)
+#define PL111_REG_LCD_RIS ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x020)
+#define PL111_REG_LCD_MIS ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x024)
+#define PL111_REG_LCD_ICR ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x028)
+#define PL111_REG_LCD_UP_CURR ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x02C)
+#define PL111_REG_LCD_LP_CURR ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x030)
+#define PL111_REG_LCD_PALETTE ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x200)
+
+// Identification Register Offsets
+#define PL111_REG_CLCD_PERIPH_ID_0 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE0)
+#define PL111_REG_CLCD_PERIPH_ID_1 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE4)
+#define PL111_REG_CLCD_PERIPH_ID_2 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE8)
+#define PL111_REG_CLCD_PERIPH_ID_3 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFEC)
+#define PL111_REG_CLCD_P_CELL_ID_0 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF0)
+#define PL111_REG_CLCD_P_CELL_ID_1 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF4)
+#define PL111_REG_CLCD_P_CELL_ID_2 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF8)
+#define PL111_REG_CLCD_P_CELL_ID_3 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFFC)
+
+#define PL111_CLCD_PERIPH_ID_0 0x11
+#define PL111_CLCD_PERIPH_ID_1 0x11
+#define PL111_CLCD_PERIPH_ID_2 0x04
+#define PL111_CLCD_PERIPH_ID_3 0x00
+#define PL111_CLCD_P_CELL_ID_0 0x0D
+#define PL111_CLCD_P_CELL_ID_1 0xF0
+#define PL111_CLCD_P_CELL_ID_2 0x05
+#define PL111_CLCD_P_CELL_ID_3 0xB1
+
+/**********************************************************************/
+
+// Register components (register bits)
+
+// This should make life easier to program specific settings in the different registers
+// by simplifying the setting up of the individual bits of each register
+// and then assembling the final register value.
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define HOR_AXIS_PANEL(hbp,hfp,hsw,hor_res) (UINT32)(((UINT32)(hbp) << 24) | ((UINT32)(hfp) << 16) | ((UINT32)(hsw) << 8) | (((UINT32)((hor_res)/16)-1) << 2))
+
+// Register: PL111_REG_LCD_TIMING_1
+#define VER_AXIS_PANEL(vbp,vfp,vsw,ver_res) (UINT32)(((UINT32)(vbp) << 24) | ((UINT32)(vfp) << 16) | ((UINT32)(vsw) << 10) | ((ver_res)-1))
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_SHIFT_PCD_HI 27
+#define PL111_BIT_SHIFT_BCD 26
+#define PL111_BIT_SHIFT_CPL 16
+#define PL111_BIT_SHIFT_IOE 14
+#define PL111_BIT_SHIFT_IPC 13
+#define PL111_BIT_SHIFT_IHS 12
+#define PL111_BIT_SHIFT_IVS 11
+#define PL111_BIT_SHIFT_ACB 6
+#define PL111_BIT_SHIFT_CLKSEL 5
+#define PL111_BIT_SHIFT_PCD_LO 0
+
+#define PL111_BCD (1 << 26)
+#define PL111_IPC (1 << 13)
+#define PL111_IHS (1 << 12)
+#define PL111_IVS (1 << 11)
+
+#define CLK_SIG_POLARITY(hor_res) (UINT32)(PL111_BCD | PL111_IPC | PL111_IHS | PL111_IVS | (((hor_res)-1) << 16))
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_SHIFT_LEE 16
+#define PL111_BIT_SHIFT_LED 0
+
+#define PL111_CTRL_WATERMARK (1 << 16)
+#define PL111_CTRL_LCD_V_COMP (1 << 12)
+#define PL111_CTRL_LCD_PWR (1 << 11)
+#define PL111_CTRL_BEPO (1 << 10)
+#define PL111_CTRL_BEBO (1 << 9)
+#define PL111_CTRL_BGR (1 << 8)
+#define PL111_CTRL_LCD_DUAL (1 << 7)
+#define PL111_CTRL_LCD_MONO_8 (1 << 6)
+#define PL111_CTRL_LCD_TFT (1 << 5)
+#define PL111_CTRL_LCD_BW (1 << 4)
+#define PL111_CTRL_LCD_1BPP (0 << 1)
+#define PL111_CTRL_LCD_2BPP (1 << 1)
+#define PL111_CTRL_LCD_4BPP (2 << 1)
+#define PL111_CTRL_LCD_8BPP (3 << 1)
+#define PL111_CTRL_LCD_16BPP (4 << 1)
+#define PL111_CTRL_LCD_24BPP (5 << 1)
+#define PL111_CTRL_LCD_16BPP_565 (6 << 1)
+#define PL111_CTRL_LCD_12BPP_444 (7 << 1)
+#define PL111_CTRL_LCD_BPP(Bpp) ((Bpp) << 1)
+#define PL111_CTRL_LCD_EN 1
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define PL111_LCD_TIMING_0_HBP(hbp) (((hbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_0_HFP(hfp) (((hfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_0_HSW(hsw) (((hsw) & 0xFF) << 8)
+#define PL111_LCD_TIMING_0_PPL(ppl) (((hsw) & 0x3F) << 2)
+
+// Register: PL111_REG_LCD_TIMING_1
+#define PL111_LCD_TIMING_1_VBP(vbp) (((vbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_1_VFP(vfp) (((vfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_1_VSW(vsw) (((vsw) & 0x3F) << 10)
+#define PL111_LCD_TIMING_1_LPP(lpp) ((lpp) & 0xFC)
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_MASK_PCD_HI 0xF8000000
+#define PL111_BIT_MASK_BCD 0x04000000
+#define PL111_BIT_MASK_CPL 0x03FF0000
+#define PL111_BIT_MASK_IOE 0x00004000
+#define PL111_BIT_MASK_IPC 0x00002000
+#define PL111_BIT_MASK_IHS 0x00001000
+#define PL111_BIT_MASK_IVS 0x00000800
+#define PL111_BIT_MASK_ACB 0x000007C0
+#define PL111_BIT_MASK_CLKSEL 0x00000020
+#define PL111_BIT_MASK_PCD_LO 0x0000001F
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_MASK_LEE 0x00010000
+#define PL111_BIT_MASK_LED 0x0000007F
+
+#endif /* _PL111LCD_H__ */
diff --git a/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf
new file mode 100644
index 000000000..757348c19
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf
@@ -0,0 +1,35 @@
+#/** @file PL111Lcd.inf
+#
+# Component description file for PL111Lcd module
+#
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL111Lcd
+ FILE_GUID = 407B4008-BF5B-11DF-9547-CF16E0D72085
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LcdHwLib
+
+[Sources.common]
+ PL111Lcd.h
+ PL111Lcd.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmPkg/ArmPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiLib
+ BaseLib
+ DebugLib
+ IoLib
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdPL111LcdBase
diff --git a/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointer.c b/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointer.c
new file mode 100644
index 000000000..64850c7de
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointer.c
@@ -0,0 +1,48 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+#include <Library/ArmLib.h>
+#include <Library/PrePiHobListPointerLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Returns the pointer to the HOB list.
+
+ This function returns the pointer to first HOB in the list.
+
+ @return The pointer to the HOB list.
+
+**/
+VOID *
+EFIAPI
+PrePeiGetHobList (
+ VOID
+ )
+{
+ return (VOID *)ArmReadTpidrurw();
+}
+
+
+
+/**
+ Updates the pointer to the HOB list.
+
+ @param HobList Hob list pointer to store
+
+**/
+EFI_STATUS
+EFIAPI
+PrePeiSetHobList (
+ IN VOID *HobList
+ )
+{
+ ArmWriteTpidrurw((UINTN)HobList);
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf b/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
new file mode 100644
index 000000000..439325e5b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
@@ -0,0 +1,26 @@
+#/** @file
+#
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PrePiHobListPointerLib
+ FILE_GUID = d751d880-5ee2-11e0-b93e-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PrePiHobListPointerLib
+
+[Sources]
+ PrePiHobListPointer.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ ArmLib
diff --git a/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.c b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.c
new file mode 100644
index 000000000..89a40d4f3
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.c
@@ -0,0 +1,197 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/ArmMmuLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+STATIC
+VOID
+InitMmu (
+ IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable
+ )
+{
+
+ VOID *TranslationTableBase;
+ UINTN TranslationTableSize;
+ RETURN_STATUS Status;
+
+ //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
+ // DRAM (even at the top of DRAM as it is the first permanent memory allocation)
+ Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
+ }
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ )
+{
+ ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable;
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
+ UINT64 ResourceLength;
+ EFI_PEI_HOB_POINTERS NextHob;
+ EFI_PHYSICAL_ADDRESS FdTop;
+ EFI_PHYSICAL_ADDRESS SystemMemoryTop;
+ EFI_PHYSICAL_ADDRESS ResourceTop;
+ BOOLEAN Found;
+
+ // Get Virtual Memory Map from the Platform Library
+ ArmPlatformGetVirtualMemoryMap (&MemoryTable);
+
+ // Ensure PcdSystemMemorySize has been set
+ ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
+
+ //
+ // Now, the permanent memory has been installed, we can call AllocatePages()
+ //
+ ResourceAttributes = (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED
+ );
+
+ //
+ // Check if the resource for the main system memory has been declared
+ //
+ Found = FALSE;
+ NextHob.Raw = GetHobList ();
+ while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
+ if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (PcdGet64 (PcdSystemMemoryBase) >= NextHob.ResourceDescriptor->PhysicalStart) &&
+ (NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength <= PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize)))
+ {
+ Found = TRUE;
+ break;
+ }
+ NextHob.Raw = GET_NEXT_HOB (NextHob);
+ }
+
+ if (!Found) {
+ // Reserved the memory space occupied by the firmware volume
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ PcdGet64 (PcdSystemMemoryBase),
+ PcdGet64 (PcdSystemMemorySize)
+ );
+ }
+
+ //
+ // Reserved the memory space occupied by the firmware volume
+ //
+
+ SystemMemoryTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemoryBase) + (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemorySize);
+ FdTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFdBaseAddress) + (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFdSize);
+
+ // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE
+ // core to overwrite this area we must create a memory allocation HOB for the region,
+ // but this only works if we split off the underlying resource descriptor as well.
+ if ((PcdGet64 (PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) {
+ Found = FALSE;
+
+ // Search for System Memory Hob that contains the firmware
+ NextHob.Raw = GetHobList ();
+ while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
+ if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (PcdGet64 (PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) &&
+ (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
+ {
+ ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
+ ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
+ ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;
+
+ if (PcdGet64 (PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) {
+ if (SystemMemoryTop != FdTop) {
+ // Create the System Memory HOB for the firmware
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ PcdGet64 (PcdFdBaseAddress),
+ PcdGet32 (PcdFdSize));
+
+ // Top of the FD is system memory available for UEFI
+ NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize);
+ NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize);
+ }
+ } else {
+ // Create the System Memory HOB for the firmware
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ PcdGet64 (PcdFdBaseAddress),
+ PcdGet32 (PcdFdSize));
+
+ // Update the HOB
+ NextHob.ResourceDescriptor->ResourceLength = PcdGet64 (PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart;
+
+ // If there is some memory available on the top of the FD then create a HOB
+ if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) {
+ // Create the System Memory HOB for the remaining region (top of the FD)
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ FdTop,
+ ResourceTop - FdTop);
+ }
+ }
+
+ // Mark the memory covering the Firmware Device as boot services data
+ BuildMemoryAllocationHob (PcdGet64 (PcdFdBaseAddress),
+ PcdGet32 (PcdFdSize),
+ EfiBootServicesData);
+
+ Found = TRUE;
+ break;
+ }
+ NextHob.Raw = GET_NEXT_HOB (NextHob);
+ }
+
+ ASSERT(Found);
+ }
+
+ // Build Memory Allocation Hob
+ InitMmu (MemoryTable);
+
+ if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
+ // Optional feature that helps prevent EFI memory map fragmentation.
+ BuildMemoryTypeInformationHob ();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
new file mode 100644
index 000000000..5df5acdb0
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
@@ -0,0 +1,60 @@
+#/** @file
+#
+# Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmMemoryInitPeiLib
+ FILE_GUID = 55ddb6e0-70b5-11e0-b33e-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MemoryInitPeiLib|SEC PEIM
+
+[Sources]
+ MemoryInitPeiLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ ArmMmuLib
+ ArmPlatformLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[Depex]
+ TRUE
diff --git a/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c
new file mode 100644
index 000000000..027fa11a8
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c
@@ -0,0 +1,144 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+
+//
+// The protocols, PPI and GUID definitions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Guid/MemoryTypeInformation.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ );
+
+// May want to put this into a library so you only need the PCD settings if you are using the feature?
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ )
+{
+ EFI_MEMORY_TYPE_INFORMATION Info[10];
+
+ Info[0].Type = EfiACPIReclaimMemory;
+ Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory);
+ Info[1].Type = EfiACPIMemoryNVS;
+ Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS);
+ Info[2].Type = EfiReservedMemoryType;
+ Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType);
+ Info[3].Type = EfiRuntimeServicesData;
+ Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData);
+ Info[4].Type = EfiRuntimeServicesCode;
+ Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode);
+ Info[5].Type = EfiBootServicesCode;
+ Info[5].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesCode);
+ Info[6].Type = EfiBootServicesData;
+ Info[6].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesData);
+ Info[7].Type = EfiLoaderCode;
+ Info[7].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderCode);
+ Info[8].Type = EfiLoaderData;
+ Info[8].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderData);
+
+ // Terminator for the list
+ Info[9].Type = EfiMaxMemoryType;
+ Info[9].NumberOfPages = 0;
+
+ BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info));
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+InitializeMemory (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN SystemMemoryBase;
+ UINT64 SystemMemoryTop;
+ UINTN FdBase;
+ UINTN FdTop;
+ UINTN UefiMemoryBase;
+
+ DEBUG ((EFI_D_LOAD | EFI_D_INFO, "Memory Init PEIM Loaded\n"));
+
+ // Ensure PcdSystemMemorySize has been set
+ ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
+ ASSERT (PcdGet64 (PcdSystemMemoryBase) < (UINT64)MAX_ALLOC_ADDRESS);
+
+ SystemMemoryBase = (UINTN)PcdGet64 (PcdSystemMemoryBase);
+ SystemMemoryTop = SystemMemoryBase + PcdGet64 (PcdSystemMemorySize);
+ if (SystemMemoryTop - 1 > MAX_ALLOC_ADDRESS) {
+ SystemMemoryTop = (UINT64)MAX_ALLOC_ADDRESS + 1;
+ }
+ FdBase = (UINTN)PcdGet64 (PcdFdBaseAddress);
+ FdTop = FdBase + (UINTN)PcdGet32 (PcdFdSize);
+
+ //
+ // Declare the UEFI memory to PEI
+ //
+
+ // In case the firmware has been shadowed in the System Memory
+ if ((FdBase >= SystemMemoryBase) && (FdTop <= SystemMemoryTop)) {
+ // Check if there is enough space between the top of the system memory and the top of the
+ // firmware to place the UEFI memory (for PEI & DXE phases)
+ if (SystemMemoryTop - FdTop >= FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)) {
+ UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ } else {
+ // Check there is enough space for the UEFI memory
+ ASSERT (SystemMemoryBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize) <= FdBase);
+
+ UefiMemoryBase = FdBase - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ }
+ } else {
+ // Check the Firmware does not overlapped with the system memory
+ ASSERT ((FdBase < SystemMemoryBase) || (FdBase >= SystemMemoryTop));
+ ASSERT ((FdTop <= SystemMemoryBase) || (FdTop > SystemMemoryTop));
+
+ UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ }
+
+ Status = PeiServicesInstallPeiMemory (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+ ASSERT_EFI_ERROR (Status);
+
+ // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
+ Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
new file mode 100644
index 000000000..f7b417cab
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
@@ -0,0 +1,69 @@
+#/** @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MemoryInit
+ FILE_GUID = c61ef796-b50d-4f98-9f78-4f6f79d800d5
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeMemory
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM
+#
+
+[Sources]
+ MemoryInitPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ ArmLib
+ ArmPlatformLib
+ MemoryInitPeiLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[Depex]
+ TRUE
diff --git a/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.c b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.c
new file mode 100644
index 000000000..84b45f414
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.c
@@ -0,0 +1,24 @@
+/** @file
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ )
+{
+ BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
new file mode 100644
index 000000000..cce8a142b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
@@ -0,0 +1,44 @@
+#/** @file
+#
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformPeiLib
+ FILE_GUID = 49d37060-70b5-11e0-aa2d-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPeiLib
+
+[Sources]
+ PlatformPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ ArmPlatformLib
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+[depex]
+ TRUE
diff --git a/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c
new file mode 100644
index 000000000..ca5a31116
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c
@@ -0,0 +1,101 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+
+//
+// The protocols, PPI and GUID definitions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Ppi/GuidedSectionExtraction.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+InitializePlatformPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ );
+
+//
+// Module globals
+//
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiBootInRecoveryModePpiGuid,
+ NULL
+};
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+InitializePlatformPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((EFI_D_LOAD | EFI_D_INFO, "Platform PEIM Loaded\n"));
+
+ Status = PeiServicesSetBootMode (ArmPlatformGetBootMode ());
+ ASSERT_EFI_ERROR (Status);
+
+ PlatformPeim ();
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (&mPpiListBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ Status = PeiServicesInstallPpi (&mPpiListRecoveryBootMode);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.inf b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.inf
new file mode 100644
index 000000000..f2b0e0f08
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.inf
@@ -0,0 +1,56 @@
+#/** @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformPei
+ FILE_GUID = 2ad0fc59-2314-4bf3-8633-13fa22a624a0
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializePlatformPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM
+#
+
+[Sources]
+ PlatformPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ ArmPlatformLib
+ PlatformPeiLib
+ PeiServicesLib
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+[Depex]
+ TRUE
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/ArchPrePeiCore.c b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/ArchPrePeiCore.c
new file mode 100644
index 000000000..fe659a244
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/ArchPrePeiCore.c
@@ -0,0 +1,46 @@
+/** @file
+* Main file supporting the transition to PEI Core in Normal World for Versatile Express
+*
+* Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+
+#include "PrePeiCore.h"
+
+VOID
+PeiCommonExceptionEntry (
+ IN UINT32 Entry,
+ IN UINTN LR
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+
+ switch (Entry) {
+ case EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Synchronous Exception at 0x%X\n\r", LR);
+ break;
+ case EXCEPT_AARCH64_IRQ:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"IRQ Exception at 0x%X\n\r", LR);
+ break;
+ case EXCEPT_AARCH64_FIQ:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"FIQ Exception at 0x%X\n\r", LR);
+ break;
+ case EXCEPT_AARCH64_SERROR:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"SError/Abort Exception at 0x%X\n\r", LR);
+ break;
+ default:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Unknown Exception at 0x%X\n\r", LR);
+ break;
+ }
+
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ while(1);
+}
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Exception.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Exception.S
new file mode 100644
index 000000000..59a3da272
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Exception.S
@@ -0,0 +1,114 @@
+#
+# Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+#include <Chipset/AArch64.h>
+#include <AsmMacroIoLibV8.h>
+#include <Base.h>
+#include <AutoGen.h>
+
+.text
+
+//============================================================
+//Default Exception Handlers
+//============================================================
+
+#define TO_HANDLER \
+ EL1_OR_EL2(x1) \
+1: mrs x1, elr_el1 /* EL1 Exception Link Register */ ;\
+ b 3f ;\
+2: mrs x1, elr_el2 /* EL2 Exception Link Register */ ;\
+3: bl ASM_PFX(PeiCommonExceptionEntry) ;
+
+
+//
+// Default Exception handlers: There is no plan to return from any of these exceptions.
+// No context saving at all.
+//
+
+VECTOR_BASE(PeiVectorTable)
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_SYNC)
+_DefaultSyncExceptHandler_t:
+ mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_IRQ)
+_DefaultIrq_t:
+ mov x0, #EXCEPT_AARCH64_IRQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_FIQ)
+_DefaultFiq_t:
+ mov x0, #EXCEPT_AARCH64_FIQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_SERR)
+_DefaultSError_t:
+ mov x0, #EXCEPT_AARCH64_SERROR
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPx_SYNC)
+_DefaultSyncExceptHandler_h:
+ mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPx_IRQ)
+_DefaultIrq_h:
+ mov x0, #EXCEPT_AARCH64_IRQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPx_FIQ)
+_DefaultFiq_h:
+ mov x0, #EXCEPT_AARCH64_FIQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPx_SERR)
+_DefaultSError_h:
+ mov x0, #EXCEPT_AARCH64_SERROR
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_SYNC)
+_DefaultSyncExceptHandler_LowerA64:
+ mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_IRQ)
+_DefaultIrq_LowerA64:
+ mov x0, #EXCEPT_AARCH64_IRQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_FIQ)
+_DefaultFiq_LowerA64:
+ mov x0, #EXCEPT_AARCH64_FIQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_SERR)
+_DefaultSError_LowerA64:
+ mov x0, #EXCEPT_AARCH64_SERROR
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_SYNC)
+_DefaultSyncExceptHandler_LowerA32:
+ mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_IRQ)
+_DefaultIrq_LowerA32:
+ mov x0, #EXCEPT_AARCH64_IRQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_FIQ)
+_DefaultFiq_LowerA32:
+ mov x0, #EXCEPT_AARCH64_FIQ
+ TO_HANDLER
+
+VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_SERR)
+_DefaultSError_LowerA32:
+ mov x0, #EXCEPT_AARCH64_SERROR
+ TO_HANDLER
+
+VECTOR_END(PeiVectorTable)
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Helper.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Helper.S
new file mode 100644
index 000000000..2a604b719
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Helper.S
@@ -0,0 +1,42 @@
+#========================================================================================
+# Copyright (c) 2011-2017, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#=======================================================================================
+
+#include <AsmMacroIoLibV8.h>
+#include <Chipset/AArch64.h>
+
+// Setup EL1 while in EL1
+ASM_FUNC(SetupExceptionLevel1)
+ mov x5, x30 // Save LR
+
+ mov x0, #CPACR_CP_FULL_ACCESS
+ bl ASM_PFX(ArmWriteCpacr) // Disable copro traps to EL1
+
+ ret x5
+
+// Setup EL2 while in EL2
+ASM_FUNC(SetupExceptionLevel2)
+ msr sctlr_el2, xzr
+ mrs x0, hcr_el2 // Read EL2 Hypervisor configuration Register
+
+ // Send all interrupts to their respective Exception levels for EL2
+ orr x0, x0, #(1 << 3) // Enable EL2 FIQ
+ orr x0, x0, #(1 << 4) // Enable EL2 IRQ
+ orr x0, x0, #(1 << 5) // Enable EL2 SError and Abort
+ msr hcr_el2, x0 // Write back our settings
+
+ msr cptr_el2, xzr // Disable copro traps to EL2
+
+ // Enable Timer access for non-secure EL1 and EL0
+ // The cnthctl_el2 register bits are architecturally
+ // UNKNOWN on reset.
+ // Disable event stream as it is not in use at this stage
+ mov x0, #(CNTHCTL_EL2_EL1PCTEN | CNTHCTL_EL2_EL1PCEN)
+ msr cnthctl_el2, x0
+
+ ret
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/PrePeiCoreEntryPoint.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/PrePeiCoreEntryPoint.S
new file mode 100644
index 000000000..8ecec234b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/PrePeiCoreEntryPoint.S
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+
+ASM_FUNC(_ModuleEntryPoint)
+ // Do early platform specific actions
+ bl ASM_PFX(ArmPlatformPeiBootAction)
+
+// NOTE: We could be booting from EL3, EL2 or EL1. Need to correctly detect
+// and configure the system accordingly. EL2 is default if possible.
+// If we started in EL3 we need to switch and run at EL2.
+// If we are running at EL2 stay in EL2
+// If we are starting at EL1 stay in EL1.
+
+// If started at EL3 Sec is run and switches to EL2 before jumping to PEI.
+// If started at EL1 or EL2 Sec jumps directly to PEI without making any
+// changes.
+
+// Which EL are we running at? Every EL needs some level of setup...
+// We should not run this code in EL3
+ EL1_OR_EL2(x0)
+1:bl ASM_PFX(SetupExceptionLevel1)
+ b ASM_PFX(MainEntryPoint)
+2:bl ASM_PFX(SetupExceptionLevel2)
+ b ASM_PFX(MainEntryPoint)
+
+ASM_PFX(MainEntryPoint):
+ // Identify CPU ID
+ bl ASM_PFX(ArmReadMpidr)
+ // Keep a copy of the MpId register value
+ mov x5, x0
+
+ // Is it the Primary Core ?
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ MOV64 (x1, FixedPcdGet64(PcdCPUCoresStackBase) + FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+
+ // x0 is equal to 1 if I am the primary core
+ cmp x0, #1
+ b.eq _SetupPrimaryCoreStack
+
+_SetupSecondaryCoreStack:
+ // x1 contains the base of the secondary stacks
+
+ // Get the Core Position
+ mov x6, x1 // Save base of the secondary stacks
+ mov x0, x5
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
+ add x0, x0, #1
+
+ // StackOffset = CorePos * StackSize
+ MOV32 (x2, FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ mul x0, x0, x2
+ // SP = StackBase + StackOffset
+ add sp, x6, x0
+
+_PrepareArguments:
+ // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector
+ MOV64 (x2, FixedPcdGet64(PcdFvBaseAddress))
+ ldr x1, [x2, #8]
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr x3, =ASM_PFX(CEntryPoint)
+
+ // Set the frame pointer to NULL so any backtraces terminate here
+ mov x29, xzr
+
+ // Jump to PrePeiCore C code
+ // x0 = mp_id
+ // x1 = pei_core_address
+ mov x0, x5
+ blr x3
+
+_SetupPrimaryCoreStack:
+ mov sp, x1
+ MOV64 (x8, FixedPcdGet64 (PcdCPUCoresStackBase))
+ MOV64 (x9, FixedPcdGet32 (PcdInitValueInTempStack) |\
+ FixedPcdGet32 (PcdInitValueInTempStack) << 32)
+0:stp x9, x9, [x8], #16
+ cmp x8, x1
+ b.lt 0b
+ b _PrepareArguments
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/SwitchStack.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/SwitchStack.S
new file mode 100644
index 000000000..308b8764f
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/SwitchStack.S
@@ -0,0 +1,32 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLibV8.h>
+
+#/**
+# This allows the caller to switch the stack and return
+#
+# @param StackDelta Signed amount by which to modify the stack pointer
+#
+# @return Nothing. Goes to the Entry Point passing in the new parameters
+#
+#**/
+#VOID
+#EFIAPI
+#SecSwitchStack (
+# VOID *StackDelta
+# )#
+#
+ASM_FUNC(SecSwitchStack)
+ mov x1, sp
+ add x1, x0, x1
+ mov sp, x1
+ ret
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c
new file mode 100644
index 000000000..9a8386218
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c
@@ -0,0 +1,56 @@
+/** @file
+* Main file supporting the transition to PEI Core in Normal World for Versatile Express
+*
+* Copyright (c) 2012, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+
+#include "PrePeiCore.h"
+
+VOID
+PeiCommonExceptionEntry (
+ IN UINT32 Entry,
+ IN UINTN LR
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+
+ switch (Entry) {
+ case 0:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Reset Exception at 0x%X\n\r",LR);
+ break;
+ case 1:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Undefined Exception at 0x%X\n\r",LR);
+ break;
+ case 2:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"SWI Exception at 0x%X\n\r",LR);
+ break;
+ case 3:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"PrefetchAbort Exception at 0x%X\n\r",LR);
+ break;
+ case 4:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"DataAbort Exception at 0x%X\n\r",LR);
+ break;
+ case 5:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Reserved Exception at 0x%X\n\r",LR);
+ break;
+ case 6:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"IRQ Exception at 0x%X\n\r",LR);
+ break;
+ case 7:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"FIQ Exception at 0x%X\n\r",LR);
+ break;
+ default:
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Unknown Exception at 0x%X\n\r",LR);
+ break;
+ }
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+ while(1);
+}
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S
new file mode 100644
index 000000000..956ae8471
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2011, ARM Limited. All rights reserved.
+//
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+#include <AsmMacroIoLib.h>
+#include <Base.h>
+#include <AutoGen.h>
+
+#start of the code section
+.text
+.align 5
+
+# IMPORT
+GCC_ASM_IMPORT(PeiCommonExceptionEntry)
+
+# EXPORT
+GCC_ASM_EXPORT(PeiVectorTable)
+
+//============================================================
+//Default Exception Handlers
+//============================================================
+
+
+ASM_PFX(PeiVectorTable):
+ b _DefaultResetHandler
+ b _DefaultUndefined
+ b _DefaultSWI
+ b _DefaultPrefetchAbort
+ b _DefaultDataAbort
+ b _DefaultReserved
+ b _DefaultIrq
+ b _DefaultFiq
+
+//
+// Default Exception handlers: There is no plan to return from any of these exceptions.
+// No context saving at all.
+//
+_DefaultResetHandler:
+ mov r1, lr
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #0
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultUndefined:
+ sub r1, LR, #4
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #1
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultSWI:
+ sub r1, LR, #4
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #2
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultPrefetchAbort:
+ sub r1, LR, #4
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #3
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultDataAbort:
+ sub r1, LR, #8
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #4
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultReserved:
+ mov r1, lr
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #5
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultIrq:
+ sub r1, LR, #4
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #6
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
+_DefaultFiq:
+ sub r1, LR, #4
+ # Switch to SVC for common stack
+ cps #0x13
+ mov r0, #7
+ blx ASM_PFX(PeiCommonExceptionEntry)
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.asm b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.asm
new file mode 100644
index 000000000..28d625e67
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.asm
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2011, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AutoGen.h>
+
+ IMPORT PeiCommonExceptionEntry
+ EXPORT PeiVectorTable
+
+ PRESERVE8
+ AREA PrePeiCoreException, CODE, READONLY, CODEALIGN, ALIGN=5
+
+//============================================================
+//Default Exception Handlers
+//============================================================
+
+
+PeiVectorTable
+ b _DefaultResetHandler
+ b _DefaultUndefined
+ b _DefaultSWI
+ b _DefaultPrefetchAbort
+ b _DefaultDataAbort
+ b _DefaultReserved
+ b _DefaultIrq
+ b _DefaultFiq
+
+//
+// Default Exception handlers: There is no plan to return from any of these exceptions.
+// No context saving at all.
+//
+_DefaultResetHandler
+ mov r1, lr
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #0
+ blx PeiCommonExceptionEntry
+
+_DefaultUndefined
+ sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #1
+ blx PeiCommonExceptionEntry
+
+_DefaultSWI
+ sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #2
+ blx PeiCommonExceptionEntry
+
+_DefaultPrefetchAbort
+ sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #3
+ blx PeiCommonExceptionEntry
+
+_DefaultDataAbort
+ sub r1, LR, #8
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #4
+ blx PeiCommonExceptionEntry
+
+_DefaultReserved
+ mov r1, lr
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #5
+ blx PeiCommonExceptionEntry
+
+_DefaultIrq
+ sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #6
+ blx PeiCommonExceptionEntry
+
+_DefaultFiq
+ sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack
+ mov r0, #7
+ blx PeiCommonExceptionEntry
+
+ END
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.S
new file mode 100644
index 000000000..1c9d1b519
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.S
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLib.h>
+
+ASM_FUNC(_ModuleEntryPoint)
+ // Do early platform specific actions
+ bl ASM_PFX(ArmPlatformPeiBootAction)
+
+ // Identify CPU ID
+ bl ASM_PFX(ArmReadMpidr)
+ // Keep a copy of the MpId register value
+ mov r5, r0
+
+ // Is it the Primary Core ?
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ MOV32 (r1, FixedPcdGet64(PcdCPUCoresStackBase) + FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+
+ // r0 is equal to 1 if I am the primary core
+ cmp r0, #1
+ beq _SetupPrimaryCoreStack
+
+_SetupSecondaryCoreStack:
+ // r1 contains the base of the secondary stacks
+
+ // Get the Core Position
+ mov r6, r1 // Save base of the secondary stacks
+ mov r0, r5
+ bl ASM_PFX(ArmPlatformGetCorePosition)
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
+ add r0, r0, #1
+
+ // StackOffset = CorePos * StackSize
+ MOV32 (r2, FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ mul r0, r0, r2
+ // SP = StackBase + StackOffset
+ add sp, r6, r0
+
+_PrepareArguments:
+ // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector
+ MOV32 (r2, FixedPcdGet32(PcdFvBaseAddress))
+ ldr r1, [r2, #4]
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr r3, =ASM_PFX(CEntryPoint)
+
+ // Jump to PrePeiCore C code
+ // r0 = mp_id
+ // r1 = pei_core_address
+ mov r0, r5
+ blx r3
+
+_SetupPrimaryCoreStack:
+ mov sp, r1
+ MOV32 (r8, FixedPcdGet64 (PcdCPUCoresStackBase))
+ MOV32 (r9, FixedPcdGet32 (PcdInitValueInTempStack))
+ mov r10, r9
+ mov r11, r9
+ mov r12, r9
+0:stm r8!, {r9-r12}
+ cmp r8, r1
+ blt 0b
+ b _PrepareArguments
+
+_NeverReturn:
+ b _NeverReturn
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.asm b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.asm
new file mode 100644
index 000000000..2734b0951
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.asm
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ IMPORT CEntryPoint
+ IMPORT ArmPlatformGetCorePosition
+ IMPORT ArmPlatformIsPrimaryCore
+ IMPORT ArmReadMpidr
+ IMPORT ArmPlatformPeiBootAction
+ EXPORT _ModuleEntryPoint
+
+ PRESERVE8
+ AREA PrePeiCoreEntryPoint, CODE, READONLY
+
+StartupAddr DCD CEntryPoint
+
+_ModuleEntryPoint
+ // Do early platform specific actions
+ bl ArmPlatformPeiBootAction
+
+ // Identify CPU ID
+ bl ArmReadMpidr
+ // Keep a copy of the MpId register value
+ mov r5, r0
+
+ // Is it the Primary Core ?
+ bl ArmPlatformIsPrimaryCore
+
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ mov32 r1, FixedPcdGet64(PcdCPUCoresStackBase) + FixedPcdGet32(PcdCPUCorePrimaryStackSize)
+
+ // r0 is equal to 1 if I am the primary core
+ cmp r0, #1
+ beq _SetupPrimaryCoreStack
+
+_SetupSecondaryCoreStack
+ // r1 contains the base of the secondary stacks
+
+ // Get the Core Position
+ mov r6, r1 // Save base of the secondary stacks
+ mov r0, r5
+ bl ArmPlatformGetCorePosition
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
+ add r0, r0, #1
+
+ // StackOffset = CorePos * StackSize
+ mov32 r2, FixedPcdGet32(PcdCPUCoreSecondaryStackSize)
+ mul r0, r0, r2
+ // SP = StackBase + StackOffset
+ add sp, r6, r0
+
+_PrepareArguments
+ // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector
+ mov32 r2, FixedPcdGet32(PcdFvBaseAddress)
+ ldr r1, [r2, #4]
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr r3, StartupAddr
+
+ // Jump to PrePeiCore C code
+ // r0 = mp_id
+ // r1 = pei_core_address
+ mov r0, r5
+ blx r3
+
+_SetupPrimaryCoreStack
+ mov sp, r1
+ mov32 r8, FixedPcdGet64 (PcdCPUCoresStackBase)
+ mov32 r9, FixedPcdGet32 (PcdInitValueInTempStack)
+ mov r10, r9
+ mov r11, r9
+ mov r12, r9
+0:stm r8!, {r9-r12}
+ cmp r8, r1
+ blt 0b
+ b _PrepareArguments
+
+_NeverReturn
+ b _NeverReturn
+
+ END
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S
new file mode 100644
index 000000000..d64772b8e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S
@@ -0,0 +1,32 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLib.h>
+
+#/**
+# This allows the caller to switch the stack and return
+#
+# @param StackDelta Signed amount by which to modify the stack pointer
+#
+# @return Nothing. Goes to the Entry Point passing in the new parameters
+#
+#**/
+#VOID
+#EFIAPI
+#SecSwitchStack (
+# VOID *StackDelta
+# )#
+#
+ASM_FUNC(SecSwitchStack)
+ mov R1, R13
+ add R1, R0, R1
+ mov R13, R1
+ bx LR
+
+
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm
new file mode 100644
index 000000000..65f64805a
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm
@@ -0,0 +1,32 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+ EXPORT SecSwitchStack
+
+ AREA Switch_Stack, CODE, READONLY
+
+;/**
+; This allows the caller to switch the stack and return
+;
+; @param StackDelta Signed amount by which to modify the stack pointer
+;
+; @return Nothing. Goes to the Entry Point passing in the new parameters
+;
+;**/
+;VOID
+;EFIAPI
+;SecSwitchStack (
+; VOID *StackDelta
+; );
+;
+SecSwitchStack
+ MOV R1, SP
+ ADD R1, R0, R1
+ MOV SP, R1
+ BX LR
+ END
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c b/roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c
new file mode 100644
index 000000000..d379ad8b7
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c
@@ -0,0 +1,148 @@
+/** @file
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/ArmGicLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+#include "PrePeiCore.h"
+
+/*
+ * This is the main function for secondary cores. They loop around until a non Null value is written to
+ * SYS_FLAGS register.The SYS_FLAGS register is platform specific.
+ * Note:The secondary cores, while executing secondary_main, assumes that:
+ * : SGI 0 is configured as Non-secure interrupt
+ * : Priority Mask is configured to allow SGI 0
+ * : Interrupt Distributor and CPU interfaces are enabled
+ *
+ */
+VOID
+EFIAPI
+SecondaryMain (
+ IN UINTN MpId
+ )
+{
+ EFI_STATUS Status;
+ UINTN PpiListSize;
+ UINTN PpiListCount;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi;
+ UINTN Index;
+ UINTN ArmCoreCount;
+ ARM_CORE_INFO *ArmCoreInfoTable;
+ UINT32 ClusterId;
+ UINT32 CoreId;
+ VOID (*SecondaryStart)(VOID);
+ UINTN SecondaryEntryAddr;
+ UINTN AcknowledgeInterrupt;
+ UINTN InterruptId;
+
+ ClusterId = GET_CLUSTER_ID(MpId);
+ CoreId = GET_CORE_ID(MpId);
+
+ // Get the gArmMpCoreInfoPpiGuid
+ PpiListSize = 0;
+ ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
+ PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
+ for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
+ if (CompareGuid (PpiList->Guid, &gArmMpCoreInfoPpiGuid) == TRUE) {
+ break;
+ }
+ }
+
+ // On MP Core Platform we must implement the ARM MP Core Info PPI
+ ASSERT (Index != PpiListCount);
+
+ ArmMpCoreInfoPpi = PpiList->Ppi;
+ ArmCoreCount = 0;
+ Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
+ ASSERT_EFI_ERROR (Status);
+
+ // Find the core in the ArmCoreTable
+ for (Index = 0; Index < ArmCoreCount; Index++) {
+ if ((ArmCoreInfoTable[Index].ClusterId == ClusterId) && (ArmCoreInfoTable[Index].CoreId == CoreId)) {
+ break;
+ }
+ }
+
+ // The ARM Core Info Table must define every core
+ ASSERT (Index != ArmCoreCount);
+
+ // Clear Secondary cores MailBox
+ MmioWrite32 (ArmCoreInfoTable[Index].MailboxClearAddress, ArmCoreInfoTable[Index].MailboxClearValue);
+
+ do {
+ ArmCallWFI ();
+
+ // Read the Mailbox
+ SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress);
+
+ // Acknowledge the interrupt and send End of Interrupt signal.
+ AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), &InterruptId);
+ // Check if it is a valid interrupt ID
+ if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet64 (PcdGicDistributorBase))) {
+ // Got a valid SGI number hence signal End of Interrupt
+ ArmGicEndOfInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt);
+ }
+ } while (SecondaryEntryAddr == 0);
+
+ // Jump to secondary core entry point.
+ SecondaryStart = (VOID (*)())SecondaryEntryAddr;
+ SecondaryStart();
+
+ // The secondaries shouldn't reach here
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+PrimaryMain (
+ IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ UINTN PpiListSize;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ UINTN TemporaryRamBase;
+ UINTN TemporaryRamSize;
+
+ CreatePpiList (&PpiListSize, &PpiList);
+
+ // Enable the GIC Distributor
+ ArmGicEnableDistributor (PcdGet64(PcdGicDistributorBase));
+
+ // If ArmVe has not been built as Standalone then we need to wake up the secondary cores
+ if (FeaturePcdGet (PcdSendSgiToBringUpSecondaryCores)) {
+ // Sending SGI to all the Secondary CPU interfaces
+ ArmGicSendSgiTo (PcdGet64(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId));
+ }
+
+ // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at
+ // the base of the primary core stack
+ PpiListSize = ALIGN_VALUE(PpiListSize, CPU_STACK_ALIGNMENT);
+ TemporaryRamBase = (UINTN)PcdGet64 (PcdCPUCoresStackBase) + PpiListSize;
+ TemporaryRamSize = (UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize) - PpiListSize;
+
+ //
+ // Bind this information into the SEC hand-off state
+ // Note: this must be in sync with the stuff in the asm file
+ // Note also: HOBs (pei temp ram) MUST be above stack
+ //
+ SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet64 (PcdFvBaseAddress);
+ SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdFvSize);
+ SecCoreData.TemporaryRamBase = (VOID *)TemporaryRamBase; // We run on the primary core (and so we use the first stack)
+ SecCoreData.TemporaryRamSize = TemporaryRamSize;
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = ALIGN_VALUE (SecCoreData.TemporaryRamSize / 2, CPU_STACK_ALIGNMENT);
+ SecCoreData.StackBase = (VOID *)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
+ SecCoreData.StackSize = (TemporaryRamBase + TemporaryRamSize) - (UINTN)SecCoreData.StackBase;
+
+ // Jump to PEI core entry point
+ PeiCoreEntryPoint (&SecCoreData, PpiList);
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c b/roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c
new file mode 100644
index 000000000..1500d2bd5
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c
@@ -0,0 +1,57 @@
+/** @file
+*
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include "PrePeiCore.h"
+
+VOID
+EFIAPI
+SecondaryMain (
+ IN UINTN MpId
+ )
+{
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+PrimaryMain (
+ IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ UINTN PpiListSize;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ UINTN TemporaryRamBase;
+ UINTN TemporaryRamSize;
+
+ CreatePpiList (&PpiListSize, &PpiList);
+
+ // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at
+ // the base of the primary core stack
+ PpiListSize = ALIGN_VALUE(PpiListSize, CPU_STACK_ALIGNMENT);
+ TemporaryRamBase = (UINTN)PcdGet64 (PcdCPUCoresStackBase) + PpiListSize;
+ TemporaryRamSize = (UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize) - PpiListSize;
+
+ //
+ // Bind this information into the SEC hand-off state
+ // Note: this must be in sync with the stuff in the asm file
+ // Note also: HOBs (pei temp ram) MUST be above stack
+ //
+ SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet64 (PcdFvBaseAddress);
+ SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdFvSize);
+ SecCoreData.TemporaryRamBase = (VOID *)TemporaryRamBase; // We run on the primary core (and so we use the first stack)
+ SecCoreData.TemporaryRamSize = TemporaryRamSize;
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = ALIGN_VALUE (SecCoreData.TemporaryRamSize / 2, CPU_STACK_ALIGNMENT);
+ SecCoreData.StackBase = (VOID *)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
+ SecCoreData.StackSize = (TemporaryRamBase + TemporaryRamSize) - (UINTN)SecCoreData.StackBase;
+
+ // Jump to PEI core entry point
+ (PeiCoreEntryPoint)(&SecCoreData, PpiList);
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c
new file mode 100644
index 000000000..5202aa641
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c
@@ -0,0 +1,144 @@
+/** @file
+* Main file supporting the transition to PEI Core in Normal World for Versatile Express
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/ArmLib.h>
+
+#include "PrePeiCore.h"
+
+CONST EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { PrePeiCoreTemporaryRamSupport };
+
+CONST EFI_PEI_PPI_DESCRIPTOR gCommonPpiTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiTemporaryRamSupportPpiGuid,
+ (VOID *) &mTemporaryRamSupportPpi
+ }
+};
+
+VOID
+CreatePpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ EFI_PEI_PPI_DESCRIPTOR *PlatformPpiList;
+ UINTN PlatformPpiListSize;
+ UINTN ListBase;
+ EFI_PEI_PPI_DESCRIPTOR *LastPpi;
+
+ // Get the Platform PPIs
+ PlatformPpiListSize = 0;
+ ArmPlatformGetPlatformPpiList (&PlatformPpiListSize, &PlatformPpiList);
+
+ // Copy the Common and Platform PPis in Temporary Memory
+ ListBase = PcdGet64 (PcdCPUCoresStackBase);
+ CopyMem ((VOID*)ListBase, gCommonPpiTable, sizeof(gCommonPpiTable));
+ CopyMem ((VOID*)(ListBase + sizeof(gCommonPpiTable)), PlatformPpiList, PlatformPpiListSize);
+
+ // Set the Terminate flag on the last PPI entry
+ LastPpi = (EFI_PEI_PPI_DESCRIPTOR*)ListBase + ((sizeof(gCommonPpiTable) + PlatformPpiListSize) / sizeof(EFI_PEI_PPI_DESCRIPTOR)) - 1;
+ LastPpi->Flags |= EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+
+ *PpiList = (EFI_PEI_PPI_DESCRIPTOR*)ListBase;
+ *PpiListSize = sizeof(gCommonPpiTable) + PlatformPpiListSize;
+}
+
+VOID
+CEntryPoint (
+ IN UINTN MpId,
+ IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
+ )
+{
+ // Data Cache enabled on Primary core when MMU is enabled.
+ ArmDisableDataCache ();
+ // Invalidate instruction cache
+ ArmInvalidateInstructionCache ();
+ // Enable Instruction Caches on all cores.
+ ArmEnableInstructionCache ();
+
+ InvalidateDataCacheRange ((VOID *)(UINTN)PcdGet64 (PcdCPUCoresStackBase),
+ PcdGet32 (PcdCPUCorePrimaryStackSize));
+
+ //
+ // Note: Doesn't have to Enable CPU interface in non-secure world,
+ // as Non-secure interface is already enabled in Secure world.
+ //
+
+ // Write VBAR - The Exception Vector table must be aligned to its requirement
+ // Note: The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure
+ // 'Align=4K' is defined into your FDF for this module.
+ ASSERT (((UINTN)PeiVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
+ ArmWriteVBar ((UINTN)PeiVectorTable);
+
+ // Enable Floating Point
+ if (FixedPcdGet32 (PcdVFPEnabled)) {
+ ArmEnableVFP ();
+ }
+
+ //Note: The MMU will be enabled by MemoryPeim. Only the primary core will have the MMU on.
+
+ // If not primary Jump to Secondary Main
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+ // Initialize the Debug Agent for Source Level Debugging
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
+ SaveAndSetDebugTimerInterrupt (TRUE);
+
+ // Initialize the platform specific controllers
+ ArmPlatformInitialize (MpId);
+
+ // Goto primary Main.
+ PrimaryMain (PeiCoreEntryPoint);
+ } else {
+ SecondaryMain (MpId);
+ }
+
+ // PEI Core should always load and never return
+ ASSERT (FALSE);
+}
+
+EFI_STATUS
+EFIAPI
+PrePeiCoreTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ VOID *OldHeap;
+ VOID *NewHeap;
+ VOID *OldStack;
+ VOID *NewStack;
+ UINTN HeapSize;
+
+ HeapSize = ALIGN_VALUE (CopySize / 2, CPU_STACK_ALIGNMENT);
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize - HeapSize));
+
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+ //
+ // Migrate the temporary memory stack to permanent memory stack.
+ //
+ CopyMem (NewStack, OldStack, CopySize - HeapSize);
+
+ //
+ // Migrate the temporary memory heap to permanent memory heap.
+ //
+ CopyMem (NewHeap, OldHeap, HeapSize);
+
+ SecSwitchStack ((UINTN)NewStack - (UINTN)OldStack);
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h
new file mode 100644
index 000000000..7140c7f5b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h
@@ -0,0 +1,72 @@
+/** @file
+* Main file supporting the transition to PEI Core in Normal World for Versatile Express
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+#ifndef __PREPEICORE_H_
+#define __PREPEICORE_H_
+
+#include <Library/ArmLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+
+#include <PiPei.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+VOID
+CreatePpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ );
+
+EFI_STATUS
+EFIAPI
+PrePeiCoreTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+VOID
+SecSwitchStack (
+ INTN StackDelta
+ );
+
+// Vector Table for Pei Phase
+VOID PeiVectorTable (VOID);
+
+VOID
+EFIAPI
+PrimaryMain (
+ IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
+ );
+
+/*
+ * This is the main function for secondary cores. They loop around until a non Null value is written to
+ * SYS_FLAGS register.The SYS_FLAGS register is platform specific.
+ * Note:The secondary cores, while executing secondary_main, assumes that:
+ * : SGI 0 is configured as Non-secure interrupt
+ * : Priority Mask is configured to allow SGI 0
+ * : Interrupt Distributor and CPU interfaces are enabled
+ *
+ */
+VOID
+EFIAPI
+SecondaryMain (
+ IN UINTN MpId
+ );
+
+VOID
+PeiCommonExceptionEntry (
+ IN UINT32 Entry,
+ IN UINTN LR
+ );
+
+#endif
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
new file mode 100644
index 000000000..fb01dd1a1
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf
@@ -0,0 +1,76 @@
+#/** @file
+# Pre PeiCore - Hand-off to PEI Core in Normal World
+#
+# Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformPrePeiCore
+ FILE_GUID = b78d02bb-d0b5-4389-bc7f-b39ee846c784
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources.common]
+ MainMPCore.c
+ PrePeiCore.h
+ PrePeiCore.c
+
+[Sources.ARM]
+ Arm/ArchPrePeiCore.c
+ Arm/PrePeiCoreEntryPoint.asm | RVCT
+ Arm/PrePeiCoreEntryPoint.S | GCC
+ Arm/SwitchStack.asm | RVCT
+ Arm/SwitchStack.S | GCC
+ Arm/Exception.asm | RVCT
+ Arm/Exception.S | GCC
+
+[Sources.AARCH64]
+ AArch64/ArchPrePeiCore.c
+ AArch64/PrePeiCoreEntryPoint.S
+ AArch64/SwitchStack.S
+ AArch64/Exception.S
+ AArch64/Helper.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ ArmPlatformLib
+ CacheMaintenanceLib
+ BaseLib
+ DebugLib
+ DebugAgentLib
+ IoLib
+ ArmGicLib
+ PrintLib
+ SerialPortLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid
+ gArmMpCoreInfoPpiGuid
+
+[FeaturePcd]
+ gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+ gArmTokenSpaceGuid.PcdVFPEnabled
+
+ gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gArmTokenSpaceGuid.PcdGicSgiIntId
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
diff --git a/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
new file mode 100644
index 000000000..e9eb092d3
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
@@ -0,0 +1,70 @@
+#/** @file
+# Pre PeiCore - Hand-off to PEI Core in Normal World
+#
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformPrePeiCore
+ FILE_GUID = 469fc080-aec1-11df-927c-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources.common]
+ PrePeiCore.h
+ PrePeiCore.c
+ MainUniCore.c
+
+[Sources.ARM]
+ Arm/ArchPrePeiCore.c
+ Arm/PrePeiCoreEntryPoint.asm | RVCT
+ Arm/PrePeiCoreEntryPoint.S | GCC
+ Arm/SwitchStack.asm | RVCT
+ Arm/SwitchStack.S | GCC
+ Arm/Exception.asm | RVCT
+ Arm/Exception.S | GCC
+
+[Sources.AARCH64]
+ AArch64/ArchPrePeiCore.c
+ AArch64/PrePeiCoreEntryPoint.S
+ AArch64/SwitchStack.S
+ AArch64/Exception.S
+ AArch64/Helper.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ ArmPlatformLib
+ CacheMaintenanceLib
+ BaseLib
+ DebugLib
+ DebugAgentLib
+ IoLib
+ PrintLib
+ SerialPortLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid
+
+[FeaturePcd]
+ gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+ gArmTokenSpaceGuid.PcdVFPEnabled
+
+ gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c b/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c
new file mode 100644
index 000000000..9a172212a
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c
@@ -0,0 +1,34 @@
+/** @file
+*
+* Copyright (c) 2011-2017, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include "PrePi.h"
+
+#include <Chipset/AArch64.h>
+
+VOID
+ArchInitialize (
+ VOID
+ )
+{
+ // Enable Floating Point
+ if (FixedPcdGet32 (PcdVFPEnabled)) {
+ ArmEnableVFP ();
+ }
+
+ if (ArmReadCurrentEL () == AARCH64_EL2) {
+ // Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2
+ ArmWriteHcr (ARM_HCR_TGE);
+
+ /* Enable Timer access for non-secure EL1 and EL0
+ The cnthctl_el2 register bits are architecturally
+ UNKNOWN on reset.
+ Disable event stream as it is not in use at this stage
+ */
+ ArmWriteCntHctl (CNTHCTL_EL2_EL1PCTEN | CNTHCTL_EL2_EL1PCEN);
+ }
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S b/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S
new file mode 100644
index 000000000..4929ca42e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+
+ASM_FUNC(_ModuleEntryPoint)
+ // Do early platform specific actions
+ bl ASM_PFX(ArmPlatformPeiBootAction)
+
+ // Get ID of this CPU in Multicore system
+ bl ASM_PFX(ArmReadMpidr)
+ // Keep a copy of the MpId register value
+ mov x10, x0
+
+_SetSVCMode:
+// Check if we can install the stack at the top of the System Memory or if we need
+// to install the stacks at the bottom of the Firmware Device (case the FD is located
+// at the top of the DRAM)
+_SystemMemoryEndInit:
+ ldr x1, mSystemMemoryEnd
+
+_SetupStackPosition:
+ // r1 = SystemMemoryTop
+
+ // Calculate Top of the Firmware Device
+ MOV64 (x2, FixedPcdGet64(PcdFdBaseAddress))
+ MOV32 (x3, FixedPcdGet32(PcdFdSize) - 1)
+ sub x3, x3, #1
+ add x3, x3, x2 // x3 = FdTop = PcdFdBaseAddress + PcdFdSize
+
+ // UEFI Memory Size (stacks are allocated in this region)
+ MOV32 (x4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize))
+
+ //
+ // Reserve the memory for the UEFI region (contain stacks on its top)
+ //
+
+ // Calculate how much space there is between the top of the Firmware and the Top of the System Memory
+ subs x0, x1, x3 // x0 = SystemMemoryTop - FdTop
+ b.mi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM
+ cmp x0, x4
+ b.ge _SetupStack
+
+ // Case the top of stacks is the FdBaseAddress
+ mov x1, x2
+
+_SetupStack:
+ // x1 contains the top of the stack (and the UEFI Memory)
+
+ // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment
+ // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the
+ // top of the memory space)
+ adds x11, x1, #1
+ b.cs _SetupOverflowStack
+
+_SetupAlignedStack:
+ mov x1, x11
+ b _GetBaseUefiMemory
+
+_SetupOverflowStack:
+ // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE
+ // aligned (4KB)
+ and x1, x1, ~EFI_PAGE_MASK
+
+_GetBaseUefiMemory:
+ // Calculate the Base of the UEFI Memory
+ sub x11, x1, x4
+
+_GetStackBase:
+ // r1 = The top of the Mpcore Stacks
+ // Stack for the primary core = PrimaryCoreStack
+ MOV32 (x2, FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+ sub x12, x1, x2
+
+ // Stack for the secondary core = Number of Cores - 1
+ MOV32 (x1, (FixedPcdGet32(PcdCoreCount) - 1) * FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ sub x12, x12, x1
+
+ // x12 = The base of the MpCore Stacks (primary stack & secondary stacks)
+ mov x0, x12
+ mov x1, x10
+ //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize)
+ MOV32 (x2, FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+ MOV32 (x3, FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ bl ASM_PFX(ArmPlatformStackSet)
+
+ // Is it the Primary Core ?
+ mov x0, x10
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+ cmp x0, #1
+ bne _PrepareArguments
+
+_PrepareArguments:
+ mov x0, x10
+ mov x1, x11
+ mov x2, x12
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr x4, =ASM_PFX(CEntryPoint)
+
+ // Set the frame pointer to NULL so any backtraces terminate here
+ mov x29, xzr
+
+ // Jump to PrePiCore C code
+ // x0 = MpId
+ // x1 = UefiMemoryBase
+ // x2 = StacksBase
+ blr x4
+
+_NeverReturn:
+ b _NeverReturn
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c
new file mode 100644
index 000000000..250b622f4
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c
@@ -0,0 +1,23 @@
+/** @file
+*
+* Copyright (c) 2011 - 2013, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include "PrePi.h"
+
+VOID
+ArchInitialize (
+ VOID
+ )
+{
+ // Enable program flow prediction, if supported.
+ ArmEnableBranchPrediction ();
+
+ if (FixedPcdGet32 (PcdVFPEnabled)) {
+ ArmEnableVFP ();
+ }
+}
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S
new file mode 100644
index 000000000..ff7e3a454
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLib.h>
+
+#include <Chipset/ArmV7.h>
+
+ASM_FUNC(_ModuleEntryPoint)
+ // Do early platform specific actions
+ bl ASM_PFX(ArmPlatformPeiBootAction)
+
+ // Get ID of this CPU in Multicore system
+ bl ASM_PFX(ArmReadMpidr)
+ // Keep a copy of the MpId register value
+ mov r8, r0
+
+_SetSVCMode:
+ // Enter SVC mode, Disable FIQ and IRQ
+ mov r1, #(CPSR_MODE_SVC | CPSR_IRQ | CPSR_FIQ)
+ msr CPSR_c, r1
+
+// Check if we can install the stack at the top of the System Memory or if we need
+// to install the stacks at the bottom of the Firmware Device (case the FD is located
+// at the top of the DRAM)
+_SystemMemoryEndInit:
+ ADRL (r1, mSystemMemoryEnd)
+ ldrd r2, r3, [r1]
+ teq r3, #0
+ moveq r1, r2
+ mvnne r1, #0
+
+_SetupStackPosition:
+ // r1 = SystemMemoryTop
+
+ // Calculate Top of the Firmware Device
+ MOV32 (r2, FixedPcdGet32(PcdFdBaseAddress))
+ MOV32 (r3, FixedPcdGet32(PcdFdSize) - 1)
+ add r3, r3, r2 // r3 = FdTop = PcdFdBaseAddress + PcdFdSize
+
+ // UEFI Memory Size (stacks are allocated in this region)
+ MOV32 (r4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize))
+
+ //
+ // Reserve the memory for the UEFI region (contain stacks on its top)
+ //
+
+ // Calculate how much space there is between the top of the Firmware and the Top of the System Memory
+ subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop
+ bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM
+ cmp r0, r4
+ bge _SetupStack
+
+ // Case the top of stacks is the FdBaseAddress
+ mov r1, r2
+
+_SetupStack:
+ // r1 contains the top of the stack (and the UEFI Memory)
+
+ // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment
+ // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the
+ // top of the memory space)
+ adds r9, r1, #1
+ bcs _SetupOverflowStack
+
+_SetupAlignedStack:
+ mov r1, r9
+ b _GetBaseUefiMemory
+
+_SetupOverflowStack:
+ // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE
+ // aligned (4KB)
+ MOV32 (r9, ~EFI_PAGE_MASK & 0xFFFFFFFF)
+ and r1, r1, r9
+
+_GetBaseUefiMemory:
+ // Calculate the Base of the UEFI Memory
+ sub r9, r1, r4
+
+_GetStackBase:
+ // r1 = The top of the Mpcore Stacks
+ // Stack for the primary core = PrimaryCoreStack
+ MOV32 (r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+ sub r10, r1, r2
+
+ // Stack for the secondary core = Number of Cores - 1
+ MOV32 (r1, (FixedPcdGet32(PcdCoreCount) - 1) * FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ sub r10, r10, r1
+
+ // r10 = The base of the MpCore Stacks (primary stack & secondary stacks)
+ mov r0, r10
+ mov r1, r8
+ //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize)
+ MOV32 (r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize))
+ MOV32 (r3, FixedPcdGet32(PcdCPUCoreSecondaryStackSize))
+ bl ASM_PFX(ArmPlatformStackSet)
+
+ // Is it the Primary Core ?
+ mov r0, r8
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+ cmp r0, #1
+ bne _PrepareArguments
+
+_PrepareArguments:
+ mov r0, r8
+ mov r1, r9
+ mov r2, r10
+ mov r3, sp
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr r4, =ASM_PFX(CEntryPoint)
+
+ // Jump to PrePiCore C code
+ // r0 = MpId
+ // r1 = UefiMemoryBase
+ // r2 = StacksBase
+ blx r4
+
+_NeverReturn:
+ b _NeverReturn
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm
new file mode 100644
index 000000000..3da789205
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AutoGen.h>
+#include <Chipset/ArmV7.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ IMPORT CEntryPoint
+ IMPORT ArmPlatformIsPrimaryCore
+ IMPORT ArmReadMpidr
+ IMPORT ArmPlatformPeiBootAction
+ IMPORT ArmPlatformStackSet
+ IMPORT mSystemMemoryEnd
+
+ EXPORT _ModuleEntryPoint
+
+ PRESERVE8
+ AREA PrePiCoreEntryPoint, CODE, READONLY
+
+StartupAddr DCD CEntryPoint
+
+_ModuleEntryPoint
+ // Do early platform specific actions
+ bl ArmPlatformPeiBootAction
+
+ // Get ID of this CPU in Multicore system
+ bl ArmReadMpidr
+ // Keep a copy of the MpId register value
+ mov r8, r0
+
+_SetSVCMode
+ // Enter SVC mode, Disable FIQ and IRQ
+ mov r1, #(CPSR_MODE_SVC :OR: CPSR_IRQ :OR: CPSR_FIQ)
+ msr CPSR_c, r1
+
+// Check if we can install the stack at the top of the System Memory or if we need
+// to install the stacks at the bottom of the Firmware Device (case the FD is located
+// at the top of the DRAM)
+_SystemMemoryEndInit
+ adrll r1, mSystemMemoryEnd
+ ldrd r2, r3, [r1]
+ teq r3, #0
+ moveq r1, r2
+ mvnne r1, #0
+
+_SetupStackPosition
+ // r1 = SystemMemoryTop
+
+ // Calculate Top of the Firmware Device
+ mov32 r2, FixedPcdGet32(PcdFdBaseAddress)
+ mov32 r3, FixedPcdGet32(PcdFdSize)
+ sub r3, r3, #1
+ add r3, r3, r2 // r3 = FdTop = PcdFdBaseAddress + PcdFdSize
+
+ // UEFI Memory Size (stacks are allocated in this region)
+ mov32 r4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize)
+
+ //
+ // Reserve the memory for the UEFI region (contain stacks on its top)
+ //
+
+ // Calculate how much space there is between the top of the Firmware and the Top of the System Memory
+ subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop
+ bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM
+ cmp r0, r4
+ bge _SetupStack
+
+ // Case the top of stacks is the FdBaseAddress
+ mov r1, r2
+
+_SetupStack
+ // r1 contains the top of the stack (and the UEFI Memory)
+
+ // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment
+ // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the
+ // top of the memory space)
+ adds r9, r1, #1
+ bcs _SetupOverflowStack
+
+_SetupAlignedStack
+ mov r1, r9
+ b _GetBaseUefiMemory
+
+_SetupOverflowStack
+ // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE
+ // aligned (4KB)
+ mov32 r9, EFI_PAGE_MASK
+ and r9, r9, r1
+ sub r1, r1, r9
+
+_GetBaseUefiMemory
+ // Calculate the Base of the UEFI Memory
+ sub r9, r1, r4
+
+_GetStackBase
+ // r1 = The top of the Mpcore Stacks
+ // Stack for the primary core = PrimaryCoreStack
+ mov32 r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)
+ sub r10, r1, r2
+
+ // Stack for the secondary core = Number of Cores - 1
+ mov32 r1, (FixedPcdGet32(PcdCoreCount) - 1) * FixedPcdGet32(PcdCPUCoreSecondaryStackSize)
+ sub r10, r10, r1
+
+ // r10 = The base of the MpCore Stacks (primary stack & secondary stacks)
+ mov r0, r10
+ mov r1, r8
+ //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize)
+ mov32 r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)
+ mov32 r3, FixedPcdGet32(PcdCPUCoreSecondaryStackSize)
+ bl ArmPlatformStackSet
+
+ // Is it the Primary Core ?
+ mov r0, r8
+ bl ArmPlatformIsPrimaryCore
+ cmp r0, #1
+ bne _PrepareArguments
+
+_PrepareArguments
+ mov r0, r8
+ mov r1, r9
+ mov r2, r10
+
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr r4, StartupAddr
+
+ // Jump to PrePiCore C code
+ // r0 = MpId
+ // r1 = UefiMemoryBase
+ // r2 = StacksBase
+ blx r4
+
+_NeverReturn
+ b _NeverReturn
+
+ END
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c b/roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c
new file mode 100644
index 000000000..31cf085b6
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c
@@ -0,0 +1,99 @@
+/** @file
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include "PrePi.h"
+
+#include <Library/ArmGicLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+VOID
+PrimaryMain (
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase,
+ IN UINT64 StartTimeStamp
+ )
+{
+ // Enable the GIC Distributor
+ ArmGicEnableDistributor(PcdGet64(PcdGicDistributorBase));
+
+ // In some cases, the secondary cores are waiting for an SGI from the next stage boot loader to resume their initialization
+ if (!FixedPcdGet32(PcdSendSgiToBringUpSecondaryCores)) {
+ // Sending SGI to all the Secondary CPU interfaces
+ ArmGicSendSgiTo (PcdGet64(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId));
+ }
+
+ PrePiMain (UefiMemoryBase, StacksBase, StartTimeStamp);
+
+ // We must never return
+ ASSERT(FALSE);
+}
+
+VOID
+SecondaryMain (
+ IN UINTN MpId
+ )
+{
+ EFI_STATUS Status;
+ ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi;
+ UINTN Index;
+ UINTN ArmCoreCount;
+ ARM_CORE_INFO *ArmCoreInfoTable;
+ UINT32 ClusterId;
+ UINT32 CoreId;
+ VOID (*SecondaryStart)(VOID);
+ UINTN SecondaryEntryAddr;
+ UINTN AcknowledgeInterrupt;
+ UINTN InterruptId;
+
+ ClusterId = GET_CLUSTER_ID(MpId);
+ CoreId = GET_CORE_ID(MpId);
+
+ // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
+ Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ ArmCoreCount = 0;
+ Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
+ ASSERT_EFI_ERROR (Status);
+
+ // Find the core in the ArmCoreTable
+ for (Index = 0; Index < ArmCoreCount; Index++) {
+ if ((ArmCoreInfoTable[Index].ClusterId == ClusterId) && (ArmCoreInfoTable[Index].CoreId == CoreId)) {
+ break;
+ }
+ }
+
+ // The ARM Core Info Table must define every core
+ ASSERT (Index != ArmCoreCount);
+
+ // Clear Secondary cores MailBox
+ MmioWrite32 (ArmCoreInfoTable[Index].MailboxClearAddress, ArmCoreInfoTable[Index].MailboxClearValue);
+
+ do {
+ ArmCallWFI ();
+
+ // Read the Mailbox
+ SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress);
+
+ // Acknowledge the interrupt and send End of Interrupt signal.
+ AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), &InterruptId);
+ // Check if it is a valid interrupt ID
+ if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet64 (PcdGicDistributorBase))) {
+ // Got a valid SGI number hence signal End of Interrupt
+ ArmGicEndOfInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt);
+ }
+ } while (SecondaryEntryAddr == 0);
+
+ // Jump to secondary core entry point.
+ SecondaryStart = (VOID (*)())SecondaryEntryAddr;
+ SecondaryStart();
+
+ // The secondaries shouldn't reach here
+ ASSERT(FALSE);
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c b/roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c
new file mode 100644
index 000000000..fb2f7efd9
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c
@@ -0,0 +1,32 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include "PrePi.h"
+
+VOID
+PrimaryMain (
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase,
+ IN UINT64 StartTimeStamp
+ )
+{
+ PrePiMain (UefiMemoryBase, StacksBase, StartTimeStamp);
+
+ // We must never return
+ ASSERT(FALSE);
+}
+
+VOID
+SecondaryMain (
+ IN UINTN MpId
+ )
+{
+ // We must never get into this function on UniCore system
+ ASSERT(FALSE);
+}
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf b/roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf
new file mode 100644
index 000000000..053f9fd9e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf
@@ -0,0 +1,107 @@
+#/** @file
+#
+# (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformPrePiMPCore
+ FILE_GUID = d959e387-7b91-452c-90e0-a1dbac90ddb8
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources]
+ PrePi.h
+ PrePi.c
+ MainMPCore.c
+
+[Sources.ARM]
+ Arm/ArchPrePi.c
+ Arm/ModuleEntryPoint.S | GCC
+ Arm/ModuleEntryPoint.asm | RVCT
+
+[Sources.AArch64]
+ AArch64/ArchPrePi.c
+ AArch64/ModuleEntryPoint.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ CacheMaintenanceLib
+ DebugLib
+ DebugAgentLib
+ ArmLib
+ ArmGicLib
+ IoLib
+ TimerLib
+ SerialPortLib
+ ExtractGuidedSectionLib
+ LzmaDecompressLib
+ DebugAgentLib
+ PrePiLib
+ ArmPlatformLib
+ ArmPlatformStackLib
+ MemoryAllocationLib
+ HobLib
+ PrePiHobListPointerLib
+ PlatformPeiLib
+ MemoryInitPeiLib
+
+[Ppis]
+ gArmMpCoreInfoPpiGuid
+
+[Guids]
+ gArmMpCoreInfoGuid
+ gEfiFirmwarePerformanceGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+ gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdVFPEnabled
+
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gArmTokenSpaceGuid.PcdGicSgiIntId
+
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf b/roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf
new file mode 100644
index 000000000..78d218ae0
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf
@@ -0,0 +1,103 @@
+#/** @file
+#
+# (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmPlatformPrePiUniCore
+ FILE_GUID = d959e387-7b91-452c-90e0-a1dbac90ddb8
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources]
+ PrePi.h
+ PrePi.c
+ MainUniCore.c
+
+[Sources.ARM]
+ Arm/ArchPrePi.c
+ Arm/ModuleEntryPoint.S | GCC
+ Arm/ModuleEntryPoint.asm | RVCT
+
+[Sources.AArch64]
+ AArch64/ArchPrePi.c
+ AArch64/ModuleEntryPoint.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ CacheMaintenanceLib
+ DebugLib
+ DebugAgentLib
+ ArmLib
+ IoLib
+ TimerLib
+ SerialPortLib
+ ExtractGuidedSectionLib
+ LzmaDecompressLib
+ DebugAgentLib
+ PrePiLib
+ ArmPlatformLib
+ ArmPlatformStackLib
+ MemoryAllocationLib
+ HobLib
+ PrePiHobListPointerLib
+ PlatformPeiLib
+ MemoryInitPeiLib
+
+[Ppis]
+ gArmMpCoreInfoPpiGuid
+
+[Guids]
+ gArmMpCoreInfoGuid
+ gEfiFirmwarePerformanceGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+ gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdVFPEnabled
+
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+ gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/PrePi.c b/roms/edk2/ArmPlatformPkg/PrePi/PrePi.c
new file mode 100644
index 000000000..5129dd09a
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/PrePi.c
@@ -0,0 +1,214 @@
+/** @file
+*
+* Copyright (c) 2011-2017, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PrePiHobListPointerLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PerformanceLib.h>
+
+#include <Ppi/GuidedSectionExtraction.h>
+#include <Ppi/ArmMpCoreInfo.h>
+#include <Ppi/SecPerformance.h>
+
+#include "PrePi.h"
+
+#define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) || \
+ ((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= FixedPcdGet64 (PcdSystemMemoryBase)))
+
+UINT64 mSystemMemoryEnd = FixedPcdGet64(PcdSystemMemoryBase) +
+ FixedPcdGet64(PcdSystemMemorySize) - 1;
+
+EFI_STATUS
+GetPlatformPpi (
+ IN EFI_GUID *PpiGuid,
+ OUT VOID **Ppi
+ )
+{
+ UINTN PpiListSize;
+ UINTN PpiListCount;
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ UINTN Index;
+
+ PpiListSize = 0;
+ ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
+ PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
+ for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
+ if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) {
+ *Ppi = PpiList->Ppi;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+VOID
+PrePiMain (
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase,
+ IN UINT64 StartTimeStamp
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE* HobList;
+ ARM_MP_CORE_INFO_PPI* ArmMpCoreInfoPpi;
+ UINTN ArmCoreCount;
+ ARM_CORE_INFO* ArmCoreInfoTable;
+ EFI_STATUS Status;
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+ UINTN StacksSize;
+ FIRMWARE_SEC_PERFORMANCE Performance;
+
+ // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
+ ASSERT (IS_XIP() ||
+ ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) &&
+ ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd)));
+
+ // Initialize the architecture specific bits
+ ArchInitialize ();
+
+ // Initialize the Serial Port
+ SerialPortInitialize ();
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
+ (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ // Initialize the Debug Agent for Source Level Debugging
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
+ SaveAndSetDebugTimerInterrupt (TRUE);
+
+ // Declare the PI/UEFI memory region
+ HobList = HobConstructor (
+ (VOID*)UefiMemoryBase,
+ FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
+ (VOID*)UefiMemoryBase,
+ (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks
+ );
+ PrePeiSetHobList (HobList);
+
+ // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
+ Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+ ASSERT_EFI_ERROR (Status);
+
+ // Create the Stacks HOB (reserve the memory for all stacks)
+ if (ArmIsMpCore ()) {
+ StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) +
+ ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize));
+ } else {
+ StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
+ }
+ BuildStackHob (StacksBase, StacksSize);
+
+ //TODO: Call CpuPei as a library
+ BuildCpuHob (ArmGetPhysicalAddressBits (), PcdGet8 (PcdPrePiCpuIoSize));
+
+ if (ArmIsMpCore ()) {
+ // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid
+ Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
+
+ // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
+ ASSERT_EFI_ERROR (Status);
+
+ // Build the MP Core Info Table
+ ArmCoreCount = 0;
+ Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
+ if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) {
+ // Build MPCore Info HOB
+ BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount);
+ }
+ }
+
+ // Store timer value logged at the beginning of firmware image execution
+ Performance.ResetEnd = GetTimeInNanoSecond (StartTimeStamp);
+
+ // Build SEC Performance Data Hob
+ BuildGuidDataHob (&gEfiFirmwarePerformanceGuid, &Performance, sizeof (Performance));
+
+ // Set the Boot Mode
+ SetBootMode (ArmPlatformGetBootMode ());
+
+ // Initialize Platform HOBs (CpuHob and FvHob)
+ Status = PlatformPeim ();
+ ASSERT_EFI_ERROR (Status);
+
+ // Now, the HOB List has been initialized, we can register performance information
+ PERF_START (NULL, "PEI", NULL, StartTimeStamp);
+
+ // SEC phase needs to run library constructors by hand.
+ ProcessLibraryConstructorList ();
+
+ // Assume the FV that contains the SEC (our code) also contains a compressed FV.
+ Status = DecompressFirstFv ();
+ ASSERT_EFI_ERROR (Status);
+
+ // Load the DXE Core and transfer control to it
+ Status = LoadDxeCoreFromFv (NULL, 0);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+CEntryPoint (
+ IN UINTN MpId,
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase
+ )
+{
+ UINT64 StartTimeStamp;
+
+ // Initialize the platform specific controllers
+ ArmPlatformInitialize (MpId);
+
+ if (ArmPlatformIsPrimaryCore (MpId) && PerformanceMeasurementEnabled ()) {
+ // Initialize the Timer Library to setup the Timer HW controller
+ TimerConstructor ();
+ // We cannot call yet the PerformanceLib because the HOB List has not been initialized
+ StartTimeStamp = GetPerformanceCounter ();
+ } else {
+ StartTimeStamp = 0;
+ }
+
+ // Data Cache enabled on Primary core when MMU is enabled.
+ ArmDisableDataCache ();
+ // Invalidate instruction cache
+ ArmInvalidateInstructionCache ();
+ // Enable Instruction Caches on all cores.
+ ArmEnableInstructionCache ();
+
+ // Define the Global Variable region when we are not running in XIP
+ if (!IS_XIP()) {
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+ if (ArmIsMpCore()) {
+ // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
+ ArmCallSEV ();
+ }
+ } else {
+ // Wait the Primary core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
+ ArmCallWFE ();
+ }
+ }
+
+ // If not primary Jump to Secondary Main
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+
+ InvalidateDataCacheRange ((VOID *)UefiMemoryBase,
+ FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+
+ // Goto primary Main.
+ PrimaryMain (UefiMemoryBase, StacksBase, StartTimeStamp);
+ } else {
+ SecondaryMain (MpId);
+ }
+
+ // DXE Core should always load and never return
+ ASSERT (FALSE);
+}
diff --git a/roms/edk2/ArmPlatformPkg/PrePi/PrePi.h b/roms/edk2/ArmPlatformPkg/PrePi/PrePi.h
new file mode 100644
index 000000000..b64dd764a
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/PrePi/PrePi.h
@@ -0,0 +1,90 @@
+/** @file
+*
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef _PREPI_H_
+#define _PREPI_H_
+
+#include <PiPei.h>
+
+#include <Library/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/ArmPlatformLib.h>
+
+#define SerialPrint(txt) SerialPortWrite (txt, AsciiStrLen(txt)+1);
+
+extern UINT64 mSystemMemoryEnd;
+
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+ VOID
+ );
+
+VOID
+PrePiMain (
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase,
+ IN UINT64 StartTimeStamp
+ );
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ );
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ );
+
+VOID
+PrimaryMain (
+ IN UINTN UefiMemoryBase,
+ IN UINTN StacksBase,
+ IN UINT64 StartTimeStamp
+ );
+
+VOID
+SecondaryMain (
+ IN UINTN MpId
+ );
+
+// Either implemented by PrePiLib or by MemoryInitPei
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+EFI_STATUS
+GetPlatformPpi (
+ IN EFI_GUID *PpiGuid,
+ OUT VOID **Ppi
+ );
+
+// Initialize the Architecture specific controllers
+VOID
+ArchInitialize (
+ VOID
+ );
+
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+ VOID
+ );
+
+#endif /* _PREPI_H_ */
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/build_report.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/build_report.py
new file mode 100644
index 000000000..1f352e754
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/build_report.py
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import re
+
+class BuildReport:
+ PCDs = {}
+
+ def parse_platform_summary(self, file):
+ pass
+
+ def parse_pcd_report(self, report_file):
+ pcd_reg = re.compile(" (\*P|\*F|\*M| ) (\w+)(\ +)\: (.*) \((\w+)\) = (.*)\n")
+
+ for line in report_file.xreadlines():
+ stripped_line = line.strip()
+ if re.match("\<=+\>", stripped_line):
+ return
+ elif re.match("g.*Guid", stripped_line):
+ guid = stripped_line
+ self.PCDs[guid] = {}
+ else:
+ m = pcd_reg.match(line)
+ if m:
+ self.PCDs[guid][m.group(2)] = (m.group(6).strip(),m.group(5))
+
+ def parse_firmware_device(self, file):
+ pass
+
+ def parse_module_summary(self, file):
+ #print "Module Summary"
+ pass
+
+ CONST_SECTION_HEADERS = [('Platform Summary', parse_platform_summary),
+ ('Platform Configuration Database Report',parse_pcd_report),
+ ('Firmware Device (FD)',parse_firmware_device),
+ ('Module Summary',parse_module_summary)]
+
+ def __init__(self, filename = 'report.log'):
+ report_file = open(filename, 'r')
+ for line in report_file.xreadlines():
+ for section_header in BuildReport.CONST_SECTION_HEADERS:
+ if line.strip() == section_header[0]:
+ section_header[1](self, report_file)
+ #print self.PCDs
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py
new file mode 100644
index 000000000..de4332edc
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py
@@ -0,0 +1,96 @@
+#
+# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from arm_ds.debugger_v1 import Debugger
+from arm_ds.debugger_v1 import DebugException
+
+import re, sys, getopt
+
+import edk2_debugger
+
+# Reload external classes
+reload(edk2_debugger)
+
+def usage():
+ print "-v,--verbose"
+ print "-a,--all: Load all symbols"
+ print "-l,--report=: Filename for the EDK2 report log"
+ print "-m,--sysmem=(base,size): System Memory region"
+ print "-f,--fv=(base,size): Firmware region"
+ print "-r,--rom=(base,size): ROM region"
+
+verbose = False
+load_all = False
+report_file = None
+regions = []
+opts,args = getopt.getopt(sys.argv[1:], "hvar:vm:vr:vf:v", ["help","verbose","all","report=","sysmem=","rom=","fv="])
+if (opts is None) or (not opts):
+ report_file = '../../../report.log'
+else:
+ region_reg = re.compile("\((.*),(.*)\)")
+ base_reg = re.compile("(.*)")
+
+ for o,a in opts:
+ region_type = None
+ regex = None
+ m = None
+ if o in ("-h","--help"):
+ usage()
+ sys.exit()
+ elif o in ("-v","--verbose"):
+ verbose = True
+ elif o in ("-a","--all"):
+ load_all = True
+ elif o in ("-l","--report"):
+ report_file = a
+ elif o in ("-m","--sysmem"):
+ region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_SYSMEM
+ regex = region_reg
+ elif o in ("-f","--fv"):
+ region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_FV
+ regex = region_reg
+ elif o in ("-r","--rom"):
+ region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_ROM
+ regex = region_reg
+ else:
+ assert False, "Unhandled option (%s)" % o
+
+ if region_type:
+ m = regex.match(a)
+ if m:
+ if regex.groups == 1:
+ regions.append((region_type,int(m.group(1),0),0))
+ else:
+ regions.append((region_type,int(m.group(1),0),int(m.group(2),0)))
+ else:
+ if regex.groups == 1:
+ raise Exception('cmd_load_symbols', "Expect a base address")
+ else:
+ raise Exception('cmd_load_symbols', "Expect a region format as (base,size)")
+
+# Debugger object for accessing the debugger
+debugger = Debugger()
+
+# Initialisation commands
+ec = debugger.getExecutionContext(0)
+ec.getExecutionService().stop()
+ec.getExecutionService().waitForStop()
+# in case the execution context reference is out of date
+ec = debugger.getExecutionContext(0)
+
+try:
+ armplatform_debugger = edk2_debugger.ArmPlatformDebugger(ec, report_file, regions, verbose)
+
+ if load_all:
+ armplatform_debugger.load_all_symbols()
+ else:
+ armplatform_debugger.load_current_symbols()
+except IOError, (ErrorNumber, ErrorMessage):
+ print "Error: %s" % ErrorMessage
+except Exception, (ErrorClass, ErrorMessage):
+ print "Error(%s): %s" % (ErrorClass, ErrorMessage)
+except DebugException, de:
+ print "DebugError: %s" % (de.getMessage())
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py
new file mode 100644
index 000000000..9713f8bfa
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py
@@ -0,0 +1,225 @@
+#
+# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import os
+
+import firmware_volume
+import build_report
+import system_table
+
+# Reload external classes
+reload(firmware_volume)
+reload(build_report)
+reload(system_table)
+
+def readMem32(executionContext, address):
+ bytes = executionContext.getMemoryService().read(address, 4, 32)
+ return struct.unpack('<I',bytes)[0]
+
+def dump_fv(ec, fv_base, fv_size):
+ fv = firmware_volume.FirmwareVolume(ec,
+ int(build.PCDs['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),
+ int(build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16))
+
+ ffs = fv.get_next_ffs()
+ while ffs != None:
+ print "# %s" % ffs
+
+ section = ffs.get_next_section()
+ while section != None:
+ print "\t%s" % section
+ try:
+ print "\t\t- %s" % section.get_debug_filepath()
+ except Exception:
+ pass
+ section = ffs.get_next_section(section)
+
+ ffs = fv.get_next_ffs(ffs)
+
+def dump_system_table(ec, mem_base, mem_size):
+ st = system_table.SystemTable(ec, mem_base, mem_size)
+
+ debug_info_table_base = st.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
+
+ debug_info_table = system_table.DebugInfoTable(ec, debug_info_table_base)
+ debug_info_table.dump()
+
+def load_symbol_from_file(ec, filename, address, verbose = False):
+ if verbose:
+ print "Add symbols of %s at 0x%x" % (filename, address)
+
+ try:
+ ec.getImageService().addSymbols(filename, address)
+ except:
+ try:
+ # We could get an exception if the symbols are already loaded
+ ec.getImageService().unloadSymbols(filename)
+ ec.getImageService().addSymbols(filename, address)
+ except:
+ print "Warning: not possible to load symbols from %s at 0x%x" % (filename, address)
+
+def is_aarch64(ec):
+ success = True
+ try:
+ # Try to access a Aarch64 specific register
+ ec.getRegisterService().getValue('X0')
+ except:
+ success = False
+ return success
+
+class ArmPlatform:
+ def __init__(self, sysmembase=None, sysmemsize=None, fvs={}):
+ self.sysmembase = sysmembase
+ self.sysmemsize = sysmemsize
+ self.fvs = fvs
+
+class ArmPlatformDebugger:
+ system_table = None
+ firmware_volumes = {}
+
+ REGION_TYPE_SYSMEM = 1
+ REGION_TYPE_ROM = 2
+ REGION_TYPE_FV = 3
+
+ def __init__(self, ec, report_log, regions, verbose = False):
+ self.ec = ec
+ self.verbose = verbose
+ fvs = []
+ sysmem_base = None
+ sysmem_size = None
+
+ if report_log and os.path.isfile(report_log):
+ try:
+ self.build = build_report.BuildReport(report_log)
+ except IOError:
+ raise IOError(2, 'Report \'%s\' is not valid' % report_log)
+
+ # Generate list of supported Firmware Volumes
+ if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16) != 0:
+ fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16)))
+ if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdSecureFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16) != 0:
+ fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16)))
+ if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdHypFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16) != 0:
+ fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16)))
+
+ sysmem_base = int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSystemMemoryBase'][0],16)
+ sysmem_size = int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSystemMemorySize'][0],16)
+ else:
+ for region in regions:
+ if region[0] == ArmPlatformDebugger.REGION_TYPE_SYSMEM:
+ sysmem_base = region[1]
+ sysmem_size = region[2]
+ elif region[0] == ArmPlatformDebugger.REGION_TYPE_FV:
+ fvs.append((region[1],region[2]))
+ elif region[0] == ArmPlatformDebugger.REGION_TYPE_ROM:
+ for base in xrange(region[1], region[1] + region[2], 0x400000):
+ signature = struct.unpack("cccc", self.ec.getMemoryService().read(base, 4, 32))
+ if signature == FirmwareVolume.CONST_FV_SIGNATURE:
+ fvs.append((base,0))
+ else:
+ print "Region type '%d' Not Supported" % region[0]
+
+ self.platform = ArmPlatform(sysmem_base, sysmem_size, fvs)
+
+ def in_sysmem(self, addr):
+ return (self.platform.sysmembase is not None) and (self.platform.sysmembase <= addr) and (addr < self.platform.sysmembase + self.platform.sysmemsize)
+
+ def in_fv(self, addr):
+ return (self.get_fv_at(addr) != None)
+
+ def get_fv_at(self, addr):
+ for fv in self.platform.fvs:
+ if (fv[0] <= addr) and (addr < fv[0] + fv[1]):
+ return fv
+ return None
+
+ def load_current_symbols(self):
+ pc = int(self.ec.getRegisterService().getValue('PC')) & 0xFFFFFFFF
+ if self.in_fv(pc):
+ debug_infos = []
+
+ (fv_base, fv_size) = self.get_fv_at(pc)
+
+ if self.firmware_volumes.has_key(fv_base) == False:
+ self.firmware_volumes[fv_base] = firmware_volume.FirmwareVolume(self.ec, fv_base, fv_size)
+
+ stack_frame = self.ec.getTopLevelStackFrame()
+ info = self.firmware_volumes[fv_base].load_symbols_at(int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF, self.verbose)
+ debug_infos.append(info)
+ while stack_frame.next() is not None:
+ stack_frame = stack_frame.next()
+
+ # Stack frame attached to 'PC'
+ pc = int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF
+
+ # Check if the symbols for this stack frame have already been loaded
+ found = False
+ for debug_info in debug_infos:
+ if (pc >= debug_info[0]) and (pc < debug_info[0] + debug_info[1]):
+ found = True
+ if found == False:
+ info = self.firmware_volumes[fv_base].load_symbols_at(pc)
+ debug_infos.append(info)
+
+ #self.firmware_volumes[fv_base].load_symbols_at(pc)
+ elif self.in_sysmem(pc):
+ debug_infos = []
+
+ if self.system_table is None:
+ # Find the System Table
+ self.system_table = system_table.SystemTable(self.ec, self.platform.sysmembase, self.platform.sysmemsize)
+
+ # Find the Debug Info Table
+ debug_info_table_base = self.system_table.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
+ self.debug_info_table = system_table.DebugInfoTable(self.ec, debug_info_table_base)
+
+ stack_frame = self.ec.getTopLevelStackFrame()
+ info = self.debug_info_table.load_symbols_at(int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF, self.verbose)
+ debug_infos.append(info)
+ while stack_frame.next() is not None:
+ stack_frame = stack_frame.next()
+
+ # Stack frame attached to 'PC'
+ pc = int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF
+
+ # Check if the symbols for this stack frame have already been loaded
+ found = False
+ for debug_info in debug_infos:
+ if (pc >= debug_info[0]) and (pc < debug_info[0] + debug_info[1]):
+ found = True
+ if found == False:
+ try:
+ info = self.debug_info_table.load_symbols_at(pc)
+ debug_infos.append(info)
+ except:
+ pass
+
+ #self.debug_info_table.load_symbols_at(pc)
+ else:
+ raise Exception('ArmPlatformDebugger', "Not supported region")
+
+ def load_all_symbols(self):
+ # Load all the XIP symbols attached to the Firmware Volume
+ for (fv_base, fv_size) in self.platform.fvs:
+ if self.firmware_volumes.has_key(fv_base) == False:
+ self.firmware_volumes[fv_base] = firmware_volume.FirmwareVolume(self.ec, fv_base, fv_size)
+ self.firmware_volumes[fv_base].load_all_symbols(self.verbose)
+
+ try:
+ # Load all symbols of module loaded into System Memory
+ if self.system_table is None:
+ # Find the System Table
+ self.system_table = system_table.SystemTable(self.ec, self.platform.sysmembase, self.platform.sysmemsize)
+
+
+ # Find the Debug Info Table
+ debug_info_table_base = self.system_table.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
+ self.debug_info_table = system_table.DebugInfoTable(self.ec, debug_info_table_base)
+
+ self.debug_info_table.load_all_symbols(self.verbose)
+ except:
+ # Debugger exception could be excepted if DRAM has not been initialized or if we have not started to run from DRAM yet
+ print "Note: no symbols have been found in System Memory (possible cause: the UEFI permanent memory has been installed yet)"
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/firmware_volume.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/firmware_volume.py
new file mode 100644
index 000000000..c6d1ca830
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/firmware_volume.py
@@ -0,0 +1,328 @@
+#
+# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from arm_ds.debugger_v1 import DebugException
+
+import struct
+import string
+
+import edk2_debugger
+
+class EfiFileSection(object):
+ EFI_SECTION_PE32 = 0x10
+ EFI_SECTION_PIC = 0x11
+ EFI_SECTION_TE = 0x12
+
+ EFI_IMAGE_DEBUG_TYPE_CODEVIEW = 0x2
+
+ SIZEOF_EFI_FFS_FILE_HEADER = 0x28
+
+ def __init__(self, ec, base):
+ self.base = base
+ self.ec = ec
+
+ def __str__(self):
+ return "FileSection(type:0x%X, size:0x%x)" % (self.get_type(), self.get_size())
+
+ def get_base(self):
+ return self.base
+
+ def get_type(self):
+ return struct.unpack("B", self.ec.getMemoryService().read(self.base + 0x3, 1, 8))[0]
+
+ def get_size(self):
+ return (struct.unpack("<I", self.ec.getMemoryService().read(self.base, 4, 32))[0] & 0x00ffffff)
+
+ def get_debug_filepath(self):
+ type = self.get_type()
+ if type == EfiFileSection.EFI_SECTION_TE:
+ section = EfiSectionTE(self, ec, self.base + 0x4)
+ elif type == EfiFileSection.EFI_SECTION_PE32:
+ section = EfiSectionPE32(self, ec, self.base + 0x4)
+ else:
+ raise Exception("EfiFileSection", "No debug section")
+ return section.get_debug_filepath()
+
+class EfiSectionTE:
+ SIZEOF_EFI_TE_IMAGE_HEADER = 0x28
+ EFI_TE_IMAGE_SIGNATURE = ('V','Z')
+
+ def __init__(self, ec, base_te):
+ self.ec = ec
+ self.base_te = int(base_te)
+ te_sig = struct.unpack("cc", self.ec.getMemoryService().read(self.base_te, 2, 32))
+ if te_sig != EfiSectionTE.EFI_TE_IMAGE_SIGNATURE:
+ raise Exception("EfiFileSectionTE","TE Signature incorrect")
+
+ def get_debug_filepath(self):
+ stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
+ stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
+
+ debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_te + 0x20)
+ if debug_dir_entry_rva == 0:
+ raise Exception("EfiFileSectionTE","No debug directory for image")
+ debug_dir_entry_rva -= stripped_size
+
+ debug_type = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0xC)
+ if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
+ raise Exception("EfiFileSectionTE","Debug type is not dwarf")
+
+ debug_rva = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0x14)
+ debug_rva -= stripped_size
+
+ dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(self.base_te + debug_rva, 4, 32))
+ if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
+ raise Exception("EfiFileSectionTE","Dwarf debug signature not found")
+
+ if dwarf_sig == 0x66727764:
+ filename = self.base_te + debug_rva + 0xc
+ else:
+ filename = self.base_te + debug_rva + 0x10
+ filename = struct.unpack("400s", self.ec.getMemoryService().read(filename, 400, 32))[0]
+ return filename[0:string.find(filename,'\0')]
+
+ def get_debug_elfbase(self):
+ stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
+ stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
+
+ return self.base_te - stripped_size
+
+class EfiSectionPE32:
+ def __init__(self, ec, base_pe32):
+ self.ec = ec
+ self.base_pe32 = base_pe32
+
+ def get_debug_filepath(self):
+ # Offset from dos hdr to PE file hdr
+ file_header_offset = self.ec.getMemoryService().readMemory32(self.base_pe32 + 0x3C)
+
+ # Offset to debug dir in PE hdrs
+ debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + file_header_offset + 0xA8)
+ if debug_dir_entry_rva == 0:
+ raise Exception("EfiFileSectionPE32","No Debug Directory")
+
+ debug_type = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0xC)
+ if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
+ raise Exception("EfiFileSectionPE32","Debug type is not dwarf")
+
+
+ debug_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0x14)
+
+ dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(str(self.base_pe32 + debug_rva), 4, 32))
+ if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
+ raise Exception("EfiFileSectionPE32","Dwarf debug signature not found")
+
+ if dwarf_sig == 0x66727764:
+ filename = self.base_pe32 + debug_rva + 0xc
+ else:
+ filename = self.base_pe32 + debug_rva + 0x10
+ filename = struct.unpack("400s", self.ec.getMemoryService().read(str(filename), 400, 32))[0]
+ return filename[0:string.find(filename,'\0')]
+
+ def get_debug_elfbase(self):
+ return self.base_pe32
+
+class EfiSectionPE64:
+ def __init__(self, ec, base_pe64):
+ self.ec = ec
+ self.base_pe64 = base_pe64
+
+ def get_debug_filepath(self):
+ # Offset from dos hdr to PE file hdr (EFI_IMAGE_NT_HEADERS64)
+ file_header_offset = self.ec.getMemoryService().readMemory32(self.base_pe64 + 0x3C)
+
+ # Offset to debug dir in PE hdrs
+ debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_pe64 + file_header_offset + 0xB8)
+ if debug_dir_entry_rva == 0:
+ raise Exception("EfiFileSectionPE64","No Debug Directory")
+
+ debug_type = self.ec.getMemoryService().readMemory32(self.base_pe64 + debug_dir_entry_rva + 0xC)
+ if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
+ raise Exception("EfiFileSectionPE64","Debug type is not dwarf")
+
+
+ debug_rva = self.ec.getMemoryService().readMemory32(self.base_pe64 + debug_dir_entry_rva + 0x14)
+
+ dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(str(self.base_pe64 + debug_rva), 4, 32))
+ if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
+ raise Exception("EfiFileSectionPE64","Dwarf debug signature not found")
+
+ if dwarf_sig == 0x66727764:
+ filename = self.base_pe64 + debug_rva + 0xc
+ else:
+ filename = self.base_pe64 + debug_rva + 0x10
+ filename = struct.unpack("400s", self.ec.getMemoryService().read(str(filename), 400, 32))[0]
+ return filename[0:string.find(filename,'\0')]
+
+ def get_debug_elfbase(self):
+ return self.base_pe64
+
+class FirmwareFile:
+ EFI_FV_FILETYPE_RAW = 0x01
+ EFI_FV_FILETYPE_FREEFORM = 0x02
+ EFI_FV_FILETYPE_SECURITY_CORE = 0x03
+ EFI_FV_FILETYPE_PEI_CORE = 0x04
+ EFI_FV_FILETYPE_DXE_CORE = 0x05
+ EFI_FV_FILETYPE_PEIM = 0x06
+ EFI_FV_FILETYPE_DRIVER = 0x07
+ EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER = 0x08
+ EFI_FV_FILETYPE_APPLICATION = 0x09
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B
+ EFI_FV_FILETYPE_FFS_MIN = 0xF0
+
+ CONST_NB10_SIGNATURE = ('N','B','1','0')
+
+ def __init__(self, fv, base, ec):
+ self.fv = fv
+ self.base = base
+ self.ec = ec
+
+ def __str__(self):
+ return "FFS(state:0x%x, type:0x%X, size:0x%x)" % (self.get_state(), self.get_type(), self.get_size())
+
+ def get_base(self):
+ return self.base
+
+ def get_size(self):
+ size = (self.ec.getMemoryService().readMemory32(self.base + 0x14) & 0x00ffffff)
+
+ # Occupied size is the size considering the alignment
+ return size + ((0x8 - (size & 0x7)) & 0x7)
+
+ def get_type(self):
+ return self.ec.getMemoryService().readMemory8(self.base + 0x12)
+
+ def get_state(self):
+ state = self.ec.getMemoryService().readMemory8(self.base + 0x17)
+
+ polarity = self.fv.get_polarity()
+ if polarity:
+ state = ~state
+
+ highest_bit = 0x80;
+ while (highest_bit != 0) and ((highest_bit & state) == 0):
+ highest_bit >>= 1
+
+ return highest_bit
+
+ def get_next_section(self, section=None):
+ if section == None:
+ if self.get_type() != FirmwareFile.EFI_FV_FILETYPE_FFS_MIN:
+ section_base = self.get_base() + 0x18;
+ else:
+ return None
+ else:
+ section_base = int(section.get_base() + section.get_size())
+
+ # Align to next 4 byte boundary
+ if (section_base & 0x3) != 0:
+ section_base = section_base + 0x4 - (section_base & 0x3)
+
+ if section_base < self.get_base() + self.get_size():
+ return EfiFileSection(self.ec, section_base)
+ else:
+ return None
+
+class FirmwareVolume:
+ CONST_FV_SIGNATURE = ('_','F','V','H')
+ EFI_FVB2_ERASE_POLARITY = 0x800
+
+ DebugInfos = []
+
+ def __init__(self, ec, fv_base, fv_size):
+ self.ec = ec
+ self.fv_base = fv_base
+ self.fv_size = fv_size
+
+ try:
+ signature = struct.unpack("cccc", self.ec.getMemoryService().read(fv_base + 0x28, 4, 32))
+ except DebugException:
+ raise Exception("FirmwareVolume", "Not possible to access the defined firmware volume at [0x%X,0x%X]. Could be the used build report does not correspond to your current debugging context." % (int(fv_base),int(fv_base+fv_size)))
+ if signature != FirmwareVolume.CONST_FV_SIGNATURE:
+ raise Exception("FirmwareVolume", "This is not a valid firmware volume")
+
+ def get_size(self):
+ return self.ec.getMemoryService().readMemory32(self.fv_base + 0x20)
+
+ def get_attributes(self):
+ return self.ec.getMemoryService().readMemory32(self.fv_base + 0x2C)
+
+ def get_polarity(self):
+ attributes = self.get_attributes()
+ if attributes & FirmwareVolume.EFI_FVB2_ERASE_POLARITY:
+ return 1
+ else:
+ return 0
+
+ def get_next_ffs(self, ffs=None):
+ if ffs == None:
+ # Get the offset of the first FFS file from the FV header
+ ffs_base = self.fv_base + self.ec.getMemoryService().readMemory16(self.fv_base + 0x30)
+ else:
+ # Goto the next FFS file
+ ffs_base = int(ffs.get_base() + ffs.get_size())
+
+ # Align to next 8 byte boundary
+ if (ffs_base & 0x7) != 0:
+ ffs_base = ffs_base + 0x8 - (ffs_base & 0x7)
+
+ if ffs_base < self.fv_base + self.get_size():
+ return FirmwareFile(self, ffs_base, self.ec)
+ else:
+ return None
+
+ def get_debug_info(self):
+ self.DebugInfos = []
+
+ ffs = self.get_next_ffs()
+ while ffs != None:
+ section = ffs.get_next_section()
+ while section != None:
+ type = section.get_type()
+ if (type == EfiFileSection.EFI_SECTION_TE) or (type == EfiFileSection.EFI_SECTION_PE32):
+ self.DebugInfos.append((section.get_base(), section.get_size(), section.get_type()))
+ section = ffs.get_next_section(section)
+ ffs = self.get_next_ffs(ffs)
+
+ def load_symbols_at(self, addr, verbose = False):
+ if self.DebugInfos == []:
+ self.get_debug_info()
+
+ for debug_info in self.DebugInfos:
+ if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
+ if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
+ section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
+ elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
+ section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
+ else:
+ raise Exception('FirmwareVolume','Section Type not supported')
+
+ try:
+ edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
+ except Exception, (ErrorClass, ErrorMessage):
+ if verbose:
+ print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
+
+ return debug_info
+
+ def load_all_symbols(self, verbose = False):
+ if self.DebugInfos == []:
+ self.get_debug_info()
+
+ for debug_info in self.DebugInfos:
+ if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
+ section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
+ elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
+ section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
+ else:
+ continue
+
+ try:
+ edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
+ except Exception, (ErrorClass, ErrorMessage):
+ if verbose:
+ print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
+
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py
new file mode 100644
index 000000000..979c6ea2b
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py
@@ -0,0 +1,328 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2014, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import getopt
+import operator
+import os
+import pickle
+import sys
+from sys import argv
+from cStringIO import StringIO
+
+modules = {}
+functions = {}
+functions_addr = {}
+
+def usage():
+ print "-t,--trace: Location of the Trace file"
+ print "-s,--symbols: Location of the symbols and modules"
+
+def get_address_from_string(address):
+ return int(address.strip("S:").strip("N:").strip("EL2:").strip("EL1:"), 16)
+
+def get_module_from_addr(modules, addr):
+ for key,value in modules.items():
+ if (value['start'] <= addr) and (addr <= value['end']):
+ return key
+ return None
+
+def add_cycles_to_function(functions, func_name, addr, cycles):
+ if func_name != "<Unknown>":
+ # Check if we are still in the previous function
+ if add_cycles_to_function.prev_func_name == func_name:
+ add_cycles_to_function.prev_entry['cycles'] += cycles
+ return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
+
+ if func_name in functions.keys():
+ for module_name, module_value in functions[func_name].iteritems():
+ if (module_value['start'] <= addr) and (addr < module_value['end']):
+ module_value['cycles'] += cycles
+
+ add_cycles_to_function.prev_func_name = func_name
+ add_cycles_to_function.prev_module_name = module_name
+ add_cycles_to_function.prev_entry = module_value
+ return (func_name, module_name)
+ elif (module_value['end'] == 0):
+ module_value['cycles'] += cycles
+
+ add_cycles_to_function.prev_func_name = func_name
+ add_cycles_to_function.prev_module_name = module_name
+ add_cycles_to_function.prev_entry = module_value
+ return (func_name, module_name)
+
+ # Workaround to fix the 'info func' limitation that does not expose the 'static' function
+ module_name = get_module_from_addr(modules, addr)
+ functions[func_name] = {}
+ functions[func_name][module_name] = {}
+ functions[func_name][module_name]['start'] = 0
+ functions[func_name][module_name]['end'] = 0
+ functions[func_name][module_name]['cycles'] = cycles
+ functions[func_name][module_name]['count'] = 0
+
+ add_cycles_to_function.prev_func_name = func_name
+ add_cycles_to_function.prev_module_name = module_name
+ add_cycles_to_function.prev_entry = functions[func_name][module_name]
+ return (func_name, module_name)
+ else:
+ # Check if we are still in the previous function
+ if (add_cycles_to_function.prev_entry is not None) and (add_cycles_to_function.prev_entry['start'] <= addr) and (addr < add_cycles_to_function.prev_entry['end']):
+ add_cycles_to_function.prev_entry['cycles'] += cycles
+ return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
+
+ # Generate the key for the given address
+ key = addr & ~0x0FFF
+
+ if key not in functions_addr.keys():
+ if 'Unknown' not in functions.keys():
+ functions['Unknown'] = {}
+ if 'Unknown' not in functions['Unknown'].keys():
+ functions['Unknown']['Unknown'] = {}
+ functions['Unknown']['Unknown']['cycles'] = 0
+ functions['Unknown']['Unknown']['count'] = 0
+ functions['Unknown']['Unknown']['cycles'] += cycles
+
+ add_cycles_to_function.prev_func_name = None
+ return None
+
+ for func_key, module in functions_addr[key].iteritems():
+ for module_key, module_value in module.iteritems():
+ if (module_value['start'] <= addr) and (addr < module_value['end']):
+ module_value['cycles'] += cycles
+
+ # In case o <Unknown> we prefer to fallback on the direct search
+ add_cycles_to_function.prev_func_name = func_key
+ add_cycles_to_function.prev_module_name = module_key
+ add_cycles_to_function.prev_entry = module_value
+ return (func_key, module_key)
+
+ print "Warning: Function %s @ 0x%x not found" % (func_name, addr)
+
+ add_cycles_to_function.prev_func_name = None
+ return None
+
+# Static variables for the previous function
+add_cycles_to_function.prev_func_name = None
+add_cycles_to_function.prev_entry = None
+
+def trace_read():
+ global trace_process
+ line = trace.readline()
+ trace_process += len(line)
+ return line
+
+#
+# Parse arguments
+#
+trace_name = None
+symbols_file = None
+
+opts,args = getopt.getopt(sys.argv[1:], "ht:vs:v", ["help","trace=","symbols="])
+if (opts is None) or (not opts):
+ usage()
+ sys.exit()
+
+for o,a in opts:
+ if o in ("-h","--help"):
+ usage()
+ sys.exit()
+ elif o in ("-t","--trace"):
+ trace_name = a
+ elif o in ("-s","--symbols"):
+ symbols_file = a
+ else:
+ assert False, "Unhandled option (%s)" % o
+
+#
+# We try first to see if we run the script from DS-5
+#
+try:
+ from arm_ds.debugger_v1 import Debugger
+ from arm_ds.debugger_v1 import DebugException
+
+ # Debugger object for accessing the debugger
+ debugger = Debugger()
+
+ # Initialisation commands
+ ec = debugger.getExecutionContext(0)
+ ec.getExecutionService().stop()
+ ec.getExecutionService().waitForStop()
+ # in case the execution context reference is out of date
+ ec = debugger.getExecutionContext(0)
+
+ #
+ # Get the module name and their memory range
+ #
+ info_file = ec.executeDSCommand("info file")
+ info_file_str = StringIO(info_file)
+
+ line = info_file_str.readline().strip('\n')
+ while line != '':
+ if ("Symbols from" in line):
+ # Get the module name from the line 'Symbols from "/home/...."'
+ module_name = line.split("\"")[1].split("/")[-1]
+ modules[module_name] = {}
+
+ # Look for the text section
+ line = info_file_str.readline().strip('\n')
+ while (line != '') and ("Symbols from" not in line):
+ if ("ER_RO" in line):
+ modules[module_name]['start'] = get_address_from_string(line.split()[0])
+ modules[module_name]['end'] = get_address_from_string(line.split()[2])
+ line = info_file_str.readline().strip('\n')
+ break;
+ if (".text" in line):
+ modules[module_name]['start'] = get_address_from_string(line.split()[0])
+ modules[module_name]['end'] = get_address_from_string(line.split()[2])
+ line = info_file_str.readline().strip('\n')
+ break;
+ line = info_file_str.readline().strip('\n')
+ line = info_file_str.readline().strip('\n')
+
+ #
+ # Get the function name and their memory range
+ #
+ info_func = ec.executeDSCommand("info func")
+ info_func_str = StringIO(info_func)
+
+ # Skip the first line 'Low-level symbols ...'
+ line = info_func_str.readline().strip('\n')
+ func_prev = None
+ while line != '':
+ # We ignore all the functions after 'Functions in'
+ if ("Functions in " in line):
+ line = info_func_str.readline().strip('\n')
+ while line != '':
+ line = info_func_str.readline().strip('\n')
+ line = info_func_str.readline().strip('\n')
+ continue
+
+ if ("Low-level symbols" in line):
+ # We need to fixup the last function of the module
+ if func_prev is not None:
+ func_prev['end'] = modules[module_name]['end']
+ func_prev = None
+
+ line = info_func_str.readline().strip('\n')
+ continue
+
+ func_name = line.split()[1]
+ func_start = get_address_from_string(line.split()[0])
+ module_name = get_module_from_addr(modules, func_start)
+
+ if func_name not in functions.keys():
+ functions[func_name] = {}
+ functions[func_name][module_name] = {}
+ functions[func_name][module_name]['start'] = func_start
+ functions[func_name][module_name]['cycles'] = 0
+ functions[func_name][module_name]['count'] = 0
+
+ # Set the end address of the previous function
+ if func_prev is not None:
+ func_prev['end'] = func_start
+ func_prev = functions[func_name][module_name]
+
+ line = info_func_str.readline().strip('\n')
+
+ # Fixup the last function
+ func_prev['end'] = modules[module_name]['end']
+
+ if symbols_file is not None:
+ pickle.dump((modules, functions), open(symbols_file, "w"))
+except:
+ if symbols_file is None:
+ print "Error: Symbols file is required when run out of ARM DS-5"
+ sys.exit()
+
+ (modules, functions) = pickle.load(open(symbols_file, "r"))
+
+#
+# Build optimized table for the <Unknown> functions
+#
+functions_addr = {}
+for func_key, module in functions.iteritems():
+ for module_key, module_value in module.iteritems():
+ key = module_value['start'] & ~0x0FFF
+ if key not in functions_addr.keys():
+ functions_addr[key] = {}
+ if func_key not in functions_addr[key].keys():
+ functions_addr[key][func_key] = {}
+ functions_addr[key][func_key][module_key] = module_value
+
+#
+# Process the trace file
+#
+if trace_name is None:
+ sys.exit()
+
+trace = open(trace_name, "r")
+trace_size = os.path.getsize(trace_name)
+trace_process = 0
+
+# Get the column names from the first line
+columns = trace_read().split()
+column_addr = columns.index('Address')
+column_cycles = columns.index('Cycles')
+column_function = columns.index('Function')
+
+line = trace_read()
+i = 0
+prev_callee = None
+while line:
+ try:
+ func_name = line.split('\t')[column_function].strip()
+ address = get_address_from_string(line.split('\t')[column_addr])
+ cycles = int(line.split('\t')[column_cycles])
+ callee = add_cycles_to_function(functions, func_name, address, cycles)
+ if (prev_callee != None) and (prev_callee != callee):
+ functions[prev_callee[0]][prev_callee[1]]['count'] += 1
+ prev_callee = callee
+ except ValueError:
+ pass
+ line = trace_read()
+ if ((i % 1000000) == 0) and (i != 0):
+ percent = (trace_process * 100.00) / trace_size
+ print "Processing file ... (%.2f %%)" % (percent)
+ i = i + 1
+
+# Fixup the last callee
+functions[prev_callee[0]][prev_callee[1]]['count'] += 1
+
+#
+# Process results
+#
+functions_cycles = {}
+all_functions_cycles = {}
+total_cycles = 0
+
+for func_key, module in functions.iteritems():
+ for module_key, module_value in module.iteritems():
+ key = "%s/%s" % (module_key, func_key)
+ functions_cycles[key] = (module_value['cycles'], module_value['count'])
+ total_cycles += module_value['cycles']
+
+ if func_key not in all_functions_cycles.keys():
+ all_functions_cycles[func_key] = (module_value['cycles'], module_value['count'])
+ else:
+ all_functions_cycles[func_key] = tuple(map(sum, zip(all_functions_cycles[func_key], (module_value['cycles'], module_value['count']))))
+
+sorted_functions_cycles = sorted(functions_cycles.iteritems(), key=operator.itemgetter(1), reverse = True)
+sorted_all_functions_cycles = sorted(all_functions_cycles.items(), key=operator.itemgetter(1), reverse = True)
+
+print
+print "----"
+for (key,value) in sorted_functions_cycles[:20]:
+ if value[0] != 0:
+ print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
+ else:
+ break;
+print "----"
+for (key,value) in sorted_all_functions_cycles[:20]:
+ if value[0] != 0:
+ print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
+ else:
+ break;
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Ds5/system_table.py b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/system_table.py
new file mode 100644
index 000000000..468ee0918
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Ds5/system_table.py
@@ -0,0 +1,171 @@
+#
+# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from arm_ds.debugger_v1 import DebugException
+
+import struct
+
+import edk2_debugger
+import firmware_volume
+
+class DebugInfoTable:
+ CONST_DEBUG_INFO_TABLE_GUID = ( 0x49152E77L, 0x47641ADAL, 0xFE7AA2B7L, 0x8B5ED9FEL)
+
+ DebugInfos = []
+
+ def __init__(self, ec, debug_info_table_header_offset):
+ self.ec = ec
+ self.base = debug_info_table_header_offset
+
+ def get_debug_info(self):
+ # Get the information from EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
+ count = self.ec.getMemoryService().readMemory32(self.base + 0x4)
+ if edk2_debugger.is_aarch64(self.ec):
+ debug_info_table_base = self.ec.getMemoryService().readMemory64(self.base + 0x8)
+ else:
+ debug_info_table_base = self.ec.getMemoryService().readMemory32(self.base + 0x8)
+
+ self.DebugInfos = []
+
+ for i in range(0, count):
+ # Get the address of the structure EFI_DEBUG_IMAGE_INFO
+ if edk2_debugger.is_aarch64(self.ec):
+ debug_info = self.ec.getMemoryService().readMemory64(debug_info_table_base + (i * 8))
+ else:
+ debug_info = self.ec.getMemoryService().readMemory32(debug_info_table_base + (i * 4))
+
+ if debug_info:
+ debug_info_type = self.ec.getMemoryService().readMemory32(debug_info)
+ # Normal Debug Info Type
+ if debug_info_type == 1:
+ if edk2_debugger.is_aarch64(self.ec):
+ # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
+ loaded_image_protocol = self.ec.getMemoryService().readMemory64(debug_info + 0x8)
+
+ image_base = self.ec.getMemoryService().readMemory64(loaded_image_protocol + 0x40)
+ image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x48)
+ else:
+ # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
+ loaded_image_protocol = self.ec.getMemoryService().readMemory32(debug_info + 0x4)
+
+ image_base = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x20)
+ image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x28)
+
+ self.DebugInfos.append((image_base,image_size))
+
+ # Return (base, size)
+ def load_symbols_at(self, addr, verbose = False):
+ if self.DebugInfos == []:
+ self.get_debug_info()
+
+ found = False
+ for debug_info in self.DebugInfos:
+ if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
+ if edk2_debugger.is_aarch64(self.ec):
+ section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
+ else:
+ section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
+
+ try:
+ edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
+ except Exception, (ErrorClass, ErrorMessage):
+ if verbose:
+ print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
+
+ found = True
+ return debug_info
+
+ if found == False:
+ raise Exception('DebugInfoTable','No symbol found at 0x%x' % addr)
+
+ def load_all_symbols(self, verbose = False):
+ if self.DebugInfos == []:
+ self.get_debug_info()
+
+ for debug_info in self.DebugInfos:
+ if edk2_debugger.is_aarch64(self.ec):
+ section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
+ else:
+ section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
+
+ try:
+ edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
+ except Exception, (ErrorClass, ErrorMessage):
+ if verbose:
+ print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
+
+ def dump(self):
+ self.get_debug_info()
+ for debug_info in self.DebugInfos:
+ base_pe32 = debug_info[0]
+ if edk2_debugger.is_aarch64(self.ec):
+ section = firmware_volume.EfiSectionPE64(self.ec, base_pe32)
+ else:
+ section = firmware_volume.EfiSectionPE32(self.ec, base_pe32)
+ print section.get_debug_filepath()
+
+class SystemTable:
+ CONST_ST_SIGNATURE = ('I','B','I',' ','S','Y','S','T')
+
+ def __init__(self, ec, membase, memsize):
+ self.membase = membase
+ self.memsize = memsize
+ self.ec = ec
+
+ found = False
+
+ # Start from the top of the memory
+ offset = self.membase + self.memsize
+ # Align to highest 4MB boundary
+ offset = offset & ~0x3FFFFF
+ # We should not have a System Table at the top of the System Memory
+ offset = offset - 0x400000
+
+ # Start at top and look on 4MB boundaries for system table ptr structure
+ while offset > self.membase:
+ try:
+ signature = struct.unpack("cccccccc", self.ec.getMemoryService().read(str(offset), 8, 32))
+ except DebugException:
+ raise Exception('SystemTable','Fail to access System Memory. Ensure all the memory in the region [0x%x;0x%X] is accessible.' % (membase,membase+memsize))
+ if signature == SystemTable.CONST_ST_SIGNATURE:
+ found = True
+ if edk2_debugger.is_aarch64(self.ec):
+ self.system_table_base = self.ec.getMemoryService().readMemory64(offset + 0x8)
+ else:
+ self.system_table_base = self.ec.getMemoryService().readMemory32(offset + 0x8)
+ break
+ offset = offset - 0x400000
+
+ if not found:
+ raise Exception('SystemTable','System Table not found in System Memory [0x%x;0x%X]' % (membase,membase+memsize))
+
+ def get_configuration_table(self, conf_table_guid):
+ if edk2_debugger.is_aarch64(self.ec):
+ # Number of configuration Table entry
+ conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x68)
+
+ # Get location of the Configuration Table entries
+ conf_table_offset = self.ec.getMemoryService().readMemory64(self.system_table_base + 0x70)
+ else:
+ # Number of configuration Table entry
+ conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x40)
+
+ # Get location of the Configuration Table entries
+ conf_table_offset = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x44)
+
+ for i in range(0, conf_table_entry_count):
+ if edk2_debugger.is_aarch64(self.ec):
+ offset = conf_table_offset + (i * 0x18)
+ else:
+ offset = conf_table_offset + (i * 0x14)
+ guid = struct.unpack("<IIII", self.ec.getMemoryService().read(str(offset), 16, 32))
+ if guid == conf_table_guid:
+ if edk2_debugger.is_aarch64(self.ec):
+ return self.ec.getMemoryService().readMemory64(offset + 0x10)
+ else:
+ return self.ec.getMemoryService().readMemory32(offset + 0x10)
+
+ raise Exception('SystemTable','Configuration Table not found')
diff --git a/roms/edk2/ArmPlatformPkg/Scripts/Makefile b/roms/edk2/ArmPlatformPkg/Scripts/Makefile
new file mode 100644
index 000000000..da949dc1e
--- /dev/null
+++ b/roms/edk2/ArmPlatformPkg/Scripts/Makefile
@@ -0,0 +1,81 @@
+#/* @file
+# Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#*/
+
+# Define the following variable to specify an alternative toolchain to the one located in your PATH:
+# - RVCT_TOOLS_PATH: for RVCT and RVCTLINUX toolchains
+
+EDK2_TOOLCHAIN ?= RVCTLINUX
+EDK2_ARCH ?= ARM
+EDK2_BUILD ?= DEBUG
+
+ifeq ($(EDK2_DSC),"")
+ $(error The Makfile macro 'EDK2_DSC' must be defined with an EDK2 DSC file.)
+endif
+ifeq ("$(EDK2_DSC)","ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-FVP-AArch64.dsc")
+ BUILD_FIP=1
+ BUILD_PATH=$(WORKSPACE)/Build/ArmVExpress-FVP-AArch64
+ UEFI_BIN=FVP_AARCH64_EFI.fd
+endif
+
+ifeq ("$(OS)","Windows_NT")
+export WORKSPACE?=$(PWD)
+export EDK_TOOLS_PATH ?= $(WORKSPACE)\BaseTools
+endif
+
+SHELL := /bin/bash
+SILENT ?= @
+ECHO ?= echo
+MAKE ?= make -i -k
+RM ?= rm -f
+
+.PHONY: all clean
+
+EDK2_CONF = Conf/BuildEnv.sh Conf/build_rule.txt Conf/target.txt Conf/tools_def.txt
+
+#
+# FIP Support
+#
+ifeq ($(BUILD_FIP),"1")
+ ifeq ($(FIP_BIN),"")
+ $(info Define location of the FIP to automatically update the package after building UEFI.)
+ endif
+endif
+
+all: $(EDK2_CONF)
+ifeq ("$(OS)","Windows_NT")
+ build -a $(EDK2_ARCH) -p $(EDK2_DSC) -t $(EDK2_TOOLCHAIN) -b $(EDK2_BUILD) $(EDK2_MACROS)
+else
+ . ./edksetup.sh; build -a $(EDK2_ARCH) -p $(EDK2_DSC) -t $(EDK2_TOOLCHAIN) -b $(EDK2_BUILD) $(EDK2_MACROS)
+endif
+ifeq ("$(BUILD_FIP)","1")
+ifneq ($(FIP_BIN),"")
+ $(SILENT)which fip_create ; \
+ if [ $$? -ne 0 ]; then \
+ $(ECHO) "Warning: 'fip_create' tool is not in the PATH. The UEFI binary will not be added in the Firmware Image Package (FIP)."; \
+ else \
+ fip_create --bl33 $(BUILD_PATH)/$(EDK2_BUILD)_$(EDK2_TOOLCHAIN)/FV/$(UEFI_BIN) --dump $(FIP_BIN); \
+ fi
+endif
+endif
+
+$(EDK2_CONF):
+ifeq ("$(OS)","Windows_NT")
+ copy $(EDK_TOOLS_PATH)\Conf\build_rule.template Conf\build_rule.txt
+ copy $(EDK_TOOLS_PATH)\Conf\FrameworkDatabase.template Conf\FrameworkDatabase.txt
+ copy $(EDK_TOOLS_PATH)\Conf\target.template Conf\target.txt
+ copy $(EDK_TOOLS_PATH)\Conf\tools_def.template Conf\tools_def.txt
+else
+ . ./edksetup.sh; $(MAKE) -C BaseTools
+endif
+
+clean:
+ifeq ("$(OS)","Windows_NT")
+ build -a $(EDK2_ARCH) -p $(EDK2_DSC) -t $(EDK2_TOOLCHAIN) -b $(EDK2_BUILD) $(EDK2_MACROS) cleanall
+else
+ . ./edksetup.sh; build -a $(EDK2_ARCH) -p $(EDK2_DSC) -t $(EDK2_TOOLCHAIN) -b $(EDK2_BUILD) $(EDK2_MACROS) cleanall; \
+ rm -Rf $(EDK2_CONF) Conf/.cache
+endif