From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec | 112 ++ roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc | 121 ++ .../LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c | 876 +++++++++++++ .../LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c | 394 ++++++ .../LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h | 101 ++ .../LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf | 49 + .../Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 123 ++ .../Drivers/NorFlashDxe/NorFlashDxe.c | 1333 ++++++++++++++++++++ .../Drivers/NorFlashDxe/NorFlashDxe.h | 358 ++++++ .../Drivers/NorFlashDxe/NorFlashDxe.inf | 67 + .../Drivers/NorFlashDxe/NorFlashFvbDxe.c | 800 ++++++++++++ .../Drivers/PL061GpioDxe/PL061Gpio.c | 409 ++++++ .../Drivers/PL061GpioDxe/PL061Gpio.h | 43 + .../Drivers/PL061GpioDxe/PL061GpioDxe.inf | 45 + .../Drivers/SP805WatchdogDxe/SP805Watchdog.c | 431 +++++++ .../Drivers/SP805WatchdogDxe/SP805Watchdog.h | 42 + .../Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf | 45 + .../Include/Library/ArmPlatformLib.h | 139 ++ .../edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h | 62 + .../Include/Library/LcdPlatformLib.h | 326 +++++ .../Include/Library/NorFlashPlatformLib.h | 30 + .../Include/Library/PL011UartClockLib.h | 25 + .../ArmPlatformPkg/Include/Library/PL011UartLib.h | 183 +++ .../ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c | 403 ++++++ .../ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h | 237 ++++ .../ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf | 38 + .../ArmPlatformLibNull/AArch64/ArmPlatformHelper.S | 45 + .../ArmPlatformLibNull/Arm/ArmPlatformHelper.S | 43 + .../ArmPlatformLibNull/Arm/ArmPlatformHelper.asm | 62 + .../ArmPlatformLibNull/ArmPlatformLibNull.c | 142 +++ .../ArmPlatformLibNull/ArmPlatformLibNull.inf | 42 + .../ArmPlatformLibNull/ArmPlatformLibNullMem.c | 28 + .../AArch64/ArmPlatformStackLib.S | 99 ++ .../ArmPlatformStackLib/Arm/ArmPlatformStackLib.S | 98 ++ .../Arm/ArmPlatformStackLib.asm | 118 ++ .../ArmPlatformStackLib/ArmPlatformStackLib.inf | 34 + roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c | 174 +++ roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h | 84 ++ roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf | 39 + .../Library/LcdHwNullLib/LcdHwNullLib.c | 69 + .../Library/LcdHwNullLib/LcdHwNullLib.inf | 22 + .../LcdPlatformNullLib/LcdPlatformNullLib.c | 145 +++ .../LcdPlatformNullLib/LcdPlatformNullLib.inf | 22 + .../NorFlashPlatformNullLib.c | 28 + .../NorFlashPlatformNullLib.inf | 24 + .../PL011SerialPortLib/PL011SerialPortLib.c | 237 ++++ .../PL011SerialPortLib/PL011SerialPortLib.inf | 41 + .../Library/PL011UartClockLib/PL011UartClockLib.c | 23 + .../PL011UartClockLib/PL011UartClockLib.inf | 24 + .../Library/PL011UartLib/PL011Uart.h | 114 ++ .../Library/PL011UartLib/PL011UartLib.c | 472 +++++++ .../Library/PL011UartLib/PL011UartLib.inf | 38 + .../PL031RealTimeClockLib/PL031RealTimeClock.h | 39 + .../PL031RealTimeClockLib/PL031RealTimeClockLib.c | 356 ++++++ .../PL031RealTimeClockLib.inf | 45 + .../ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c | 165 +++ .../ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h | 143 +++ .../ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf | 35 + .../PrePiHobListPointerLib/PrePiHobListPointer.c | 48 + .../PrePiHobListPointerLib.inf | 26 + .../MemoryInitPei/MemoryInitPeiLib.c | 197 +++ .../MemoryInitPei/MemoryInitPeiLib.inf | 60 + .../ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c | 144 +++ .../MemoryInitPei/MemoryInitPeim.inf | 69 + .../ArmPlatformPkg/PlatformPei/PlatformPeiLib.c | 24 + .../ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf | 44 + .../edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c | 101 ++ .../ArmPlatformPkg/PlatformPei/PlatformPeim.inf | 56 + .../PrePeiCore/AArch64/ArchPrePeiCore.c | 46 + .../ArmPlatformPkg/PrePeiCore/AArch64/Exception.S | 114 ++ .../ArmPlatformPkg/PrePeiCore/AArch64/Helper.S | 42 + .../PrePeiCore/AArch64/PrePeiCoreEntryPoint.S | 90 ++ .../PrePeiCore/AArch64/SwitchStack.S | 32 + .../ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c | 56 + .../edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S | 96 ++ .../ArmPlatformPkg/PrePeiCore/Arm/Exception.asm | 83 ++ .../PrePeiCore/Arm/PrePeiCoreEntryPoint.S | 73 ++ .../PrePeiCore/Arm/PrePeiCoreEntryPoint.asm | 89 ++ .../ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S | 32 + .../ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm | 32 + roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c | 148 +++ roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c | 57 + roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c | 144 +++ roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h | 72 ++ .../ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf | 76 ++ .../PrePeiCore/PrePeiCoreUniCore.inf | 70 + roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c | 34 + .../PrePi/AArch64/ModuleEntryPoint.S | 116 ++ roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c | 23 + .../ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S | 124 ++ .../ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm | 142 +++ roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c | 99 ++ roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c | 32 + roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf | 107 ++ roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf | 103 ++ roms/edk2/ArmPlatformPkg/PrePi/PrePi.c | 214 ++++ roms/edk2/ArmPlatformPkg/PrePi/PrePi.h | 90 ++ .../ArmPlatformPkg/Scripts/Ds5/build_report.py | 48 + .../ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py | 96 ++ .../ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py | 225 ++++ .../ArmPlatformPkg/Scripts/Ds5/firmware_volume.py | 328 +++++ roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py | 328 +++++ .../ArmPlatformPkg/Scripts/Ds5/system_table.py | 171 +++ roms/edk2/ArmPlatformPkg/Scripts/Makefile | 81 ++ 104 files changed, 14324 insertions(+) create mode 100644 roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dec create mode 100644 roms/edk2/ArmPlatformPkg/ArmPlatformPkg.dsc create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.h create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.c create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805Watchdog.h create mode 100644 roms/edk2/ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/ArmPlatformLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/LcdHwLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/LcdPlatformLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/PL011UartClockLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Include/Library/PL011UartLib.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/AArch64/ArmPlatformHelper.S create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.S create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/Arm/ArmPlatformHelper.asm create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNullMem.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/AArch64/ArmPlatformStackLib.S create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.S create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/Arm/ArmPlatformStackLib.asm create mode 100644 roms/edk2/ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/HdLcd/HdLcd.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011Uart.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClock.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.h create mode 100644 roms/edk2/ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf create mode 100644 roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointer.c create mode 100644 roms/edk2/ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.c create mode 100644 roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c create mode 100644 roms/edk2/ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf create mode 100644 roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.c create mode 100644 roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf create mode 100644 roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.c create mode 100644 roms/edk2/ArmPlatformPkg/PlatformPei/PlatformPeim.inf create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/ArchPrePeiCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Exception.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/Helper.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/PrePeiCoreEntryPoint.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/AArch64/SwitchStack.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/ArchPrePeiCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/Exception.asm create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/PrePeiCoreEntryPoint.asm create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/Arm/SwitchStack.asm create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/MainMPCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/MainUniCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCore.h create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf create mode 100644 roms/edk2/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/AArch64/ArchPrePi.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/Arm/ArchPrePi.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.S create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/Arm/ModuleEntryPoint.asm create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/MainMPCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/MainUniCore.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/PeiMPCore.inf create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/PeiUniCore.inf create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/PrePi.c create mode 100644 roms/edk2/ArmPlatformPkg/PrePi/PrePi.h create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/build_report.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/edk2_debugger.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/firmware_volume.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/profile.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Ds5/system_table.py create mode 100644 roms/edk2/ArmPlatformPkg/Scripts/Makefile (limited to 'roms/edk2/ArmPlatformPkg') 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.
+# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.
+# Copyright (c) 2016 - 2017, Linaro Ltd. All rights reserved.
+# Copyright (c) Microsoft Corporation.
+# +# 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + +#include +#include +#include +#include +#include +#include + +#include + +#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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include + +#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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef LCD_GRAPHICS_OUTPUT_DXE_H_ +#define LCD_GRAPHICS_OUTPUT_DXE_H_ + +#include + +#include +#include +#include +#include +#include + +#include + +// +// 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.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#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; WordIndexRestoreTPL (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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __NOR_FLASH_DXE_H__ +#define __NOR_FLASH_DXE_H__ + + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#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.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + --*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 + +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 +// +// The protocols, PPI and GUID definitions for this module +// +#include +#include + +#include + +/** + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef LCD_HW_LIB_H_ +#define LCD_HW_LIB_H_ + +#include + +/** + 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + +#ifndef LCD_PLATFORM_LIB_H_ +#define LCD_PLATFORM_LIB_H_ + +#include + +#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.
+ + 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 + +#include + +/** + + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#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.
+ 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.
+# 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 +#include + +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 +#include + +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 + + 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 +#include + +#include + + +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 +#include + +/** + 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 + +//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 + +//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 + + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#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.
+ + 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.
+# +# 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 +#include +#include +#include + +/** + 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 +#include +#include +#include + +/** 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + +#include + +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.
+# +# 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.
+ Copyright (c) 2012 - 2016, ARM Ltd. All rights reserved.
+ Copyright (c) 2015, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +/** 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.
+# +# 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 + +/** + 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.
+ Copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +#include + +#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.
+# +# 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.
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright (c) 2019, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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.
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include + +#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.
+ 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.
+# 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 +#include +#include +#include + +/** + 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 + +#include +#include +#include +#include +#include +#include + +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.
+# 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 + +// +// The protocols, PPI and GUID definitions for this module +// +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include + +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.
+# Copyright (c) 2011-2014, ARM Ltd. All rights reserved.
+# 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 + +#include +#include +#include + +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 + +// +// The protocols, PPI and GUID definitions for this module +// +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +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.
+# 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 +#include + +#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 +#include +#include +#include + +.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 +#include + +// 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 + +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.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#include + +#/** +# 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 +#include + +#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 +#include +#include + +#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 + + 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 + +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 + + 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.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#include + +#/** +# 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.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; 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 + +#include + +#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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + +#include +#include + +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 + +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 + +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 + +#include + +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 +#include + + 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 + +#include + +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.
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.
+# +# 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.
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.
+# +# 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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('= 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(">= 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 != "": + # 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 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 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("