Event: TianoCore Design Meeting - APAC/NAMO - 10/15/2021
#cal-reminder
devel@edk2.groups.io Calendar <noreply@...>
Reminder: TianoCore Design Meeting - APAC/NAMO When: Where: Organizer: Ray Ni ray.ni@... Description: TOPIC
For more info, see here: https://www.tianocore.org/design-meeting/ Microsoft Teams meetingJoin on your computer or mobile appClick here to join the meeting Join with a video conferencing deviceteams@... Video Conference ID: 119 715 416 0 |
|
[RFC PATCH 4/4] EmulatorPkg: Add AArch64 Unix host build support
Akira Moroo
This commit adds AArch64 Unix host build support for EmulatorPkg.
Signed-off-by: Akira Moroo <retrage01@...> --- EmulatorPkg/EmulatorPkg.dsc | 15 ++++++++++++--- EmulatorPkg/Readme.md | 8 ++++++++ EmulatorPkg/Unix/Host/Host.inf | 5 +++++ EmulatorPkg/build.sh | 8 ++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc index 554c13ddb5..91d0176fc7 100644 --- a/EmulatorPkg/EmulatorPkg.dsc +++ b/EmulatorPkg/EmulatorPkg.dsc @@ -19,7 +19,7 @@ DSC_SPECIFICATION =3D 0x00010005=0D OUTPUT_DIRECTORY =3D Build/Emulator$(ARCH)=0D =0D - SUPPORTED_ARCHITECTURES =3D X64|IA32=0D + SUPPORTED_ARCHITECTURES =3D X64|IA32|AARCH64=0D BUILD_TARGETS =3D DEBUG|RELEASE|NOOPT=0D SKUID_IDENTIFIER =3D DEFAULT=0D FLASH_DEFINITION =3D EmulatorPkg/EmulatorPkg.fdf=0D @@ -138,6 +138,13 @@ AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib= Null.inf=0D !endif=0D =0D +[LibraryClasses.AARCH64]=0D + ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf=0D + ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf=0D + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMainte= nanceLib.inf=0D + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf=0D + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf=0D +=0D [LibraryClasses.common.SEC]=0D PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.i= nf=0D PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf=0D @@ -209,8 +216,10 @@ TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf=0D =0D [PcdsFeatureFlag]=0D - gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE=0D gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst= |FALSE=0D +=0D +[PcdsFeatureFlag.IA32,PcdsFeatureFlag.X64]=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE=0D gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables|FALSE=0D =0D [PcdsFixedAtBuild]=0D @@ -288,7 +297,7 @@ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVar= iableGuid|0x0|10=0D =0D [Components]=0D -!if "IA32" in $(ARCH) || "X64" in $(ARCH)=0D +!if "IA32" in $(ARCH) || "X64" in $(ARCH) || "AARCH64" in $(ARCH)=0D !if "MSFT" in $(FAMILY) || $(WIN_HOST_BUILD) =3D=3D TRUE=0D ##=0D # Emulator, OS WIN application=0D diff --git a/EmulatorPkg/Readme.md b/EmulatorPkg/Readme.md index 0c2eea6a9a..e3d0b58578 100644 --- a/EmulatorPkg/Readme.md +++ b/EmulatorPkg/Readme.md @@ -35,6 +35,10 @@ https://github.com/tianocore/tianocore.github.io/wiki/Em= ulatorPkg =0D `build -p EmulatorPkg\EmulatorPkg.dsc -t GCC5 -a X64`=0D =0D + * AArch64 emulator in Linux:=0D +=0D + `build -p EmulatorPkg\EmulatorPkg.dsc -t GCC5 -a AARCH64`=0D +=0D **You can start/run the emulator using the following command:**=0D * 32bit emulator in Windows:=0D =0D @@ -52,6 +56,10 @@ https://github.com/tianocore/tianocore.github.io/wiki/Em= ulatorPkg =0D `cd Build/EmulatorX64/DEBUG_GCC5/X64/ && ./Host`=0D =0D + * AArch64 emulator in Linux:=0D +=0D + `cd Build/EmulatorAARCH64/DEBUG_GCC5/AARCH64/ && ./Host`=0D +=0D **On posix-like environment with the bash shell you can use EmulatorPkg/bu= ild.sh to simplify building and running=0D emulator.**=0D =0D diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf index 43cb55aa21..fe4c6d511c 100644 --- a/EmulatorPkg/Unix/Host/Host.inf +++ b/EmulatorPkg/Unix/Host/Host.inf @@ -129,6 +129,11 @@ GCC:*_*_X64_PP_FLAGS =3D=3D -m64 -E -x assembler-with-cpp -include $(DE= ST_DIR_DEBUG)/AutoGen.h=0D GCC:*_*_X64_ASM_FLAGS =3D=3D -m64 -c -x assembler -imacros $(DEST_DIR_D= EBUG)/AutoGen.h=0D =0D + GCC:*_*_AARCH64_DLINK_FLAGS =3D=3D -fPIC -flto -o $(BIN_DIR)/Host -L/us= r/X11R6/lib=0D + GCC:*_*_AARCH64_ASM_FLAGS =3D=3D -g -c -x assembler -imacros $(DEST_DIR= _DEBUG)/AutoGen.h=0D + GCC:*_*_AARCH64_PP_FLAGS =3D=3D -E -x assembler-with-cpp -include $(DES= T_DIR_DEBUG)/AutoGen.h=0D + GCC:*_*_AARCH64_CC_FLAGS =3D=3D -c -O0 -g -fPIC -fshort-wchar -fno-stri= ct-aliasing -idirafter/usr/include -include $(DEST_DIR_DEBUG)/AutoGen.h -DU= SING_LTO -DSTRING_ARRAY_NAME=3D$(BASE_NAME)Strings=0D +=0D GCC:*_*_*_DLINK2_FLAGS =3D=3D -lpthread -ldl -lXext -lX11=0D =0D #=0D diff --git a/EmulatorPkg/build.sh b/EmulatorPkg/build.sh index 76c22dfaf8..e2ce1b8e18 100755 --- a/EmulatorPkg/build.sh +++ b/EmulatorPkg/build.sh @@ -83,6 +83,9 @@ case `uname` in x86_64) HOST_PROCESSOR=3DX64 ;; + aarch64) + HOST_PROCESSOR=3DAARCH64 + ;; esac =20 gcc_version=3D$(gcc -v 2>&1 | tail -1 | awk '{print $3}') @@ -174,6 +177,11 @@ case $PROCESSOR in LIB_NAMES=3D"ld-linux-x86-64.so.2 libdl.so.2 crt1.o crti.o crtn.o" LIB_SEARCH_PATHS=3D"/usr/lib/x86_64-linux-gnu /usr/lib64 /lib64 /usr/l= ib /lib" ;; + AARCH64) + ARCH_SIZE=3D64 + LIB_NAMES=3D"ld-linux-aarch64.so.1 libdl.so.2 crt1.o crti.o crtn.o" + LIB_SEARCH_PATHS=3D"/usr/lib/aarch64-linux-gnu /usr/lib /lib" + ;; esac =20 for libname in $LIB_NAMES --=20 2.33.0 |
|
[RFC PATCH 3/4] EmulatorPkg/Unix/Host: Add AArch64 support
Akira Moroo
Since there is no difference in calling convention between the Unix host
and the UEFI environment on AArch64, it does not require gaskets. In this commit, it defines EmulatorPkg protocols that calls the host functions without gaskets and adds AArch64 specific stack switch logic. Signed-off-by: Akira Moroo <retrage01@...> --- EmulatorPkg/Unix/Host/AArch64/Gasket.c | 50 +++++++++++ EmulatorPkg/Unix/Host/AArch64/SwitchStack.S | 42 +++++++++ EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c | 37 ++++++++ EmulatorPkg/Unix/Host/BlockIo.c | 26 ++++++ EmulatorPkg/Unix/Host/EmuThunk.c | 29 ++++++ EmulatorPkg/Unix/Host/Host.c | 32 +++++++ EmulatorPkg/Unix/Host/Host.inf | 5 +- EmulatorPkg/Unix/Host/LinuxPacketFilter.c | 38 ++++++++ EmulatorPkg/Unix/Host/PosixFileSystem.c | 94 +++++++++++++++++++- EmulatorPkg/Unix/Host/Pthreads.c | 30 ++++++- EmulatorPkg/Unix/Host/X11GraphicsWindow.c | 26 +++++- 11 files changed, 405 insertions(+), 4 deletions(-) create mode 100644 EmulatorPkg/Unix/Host/AArch64/Gasket.c create mode 100644 EmulatorPkg/Unix/Host/AArch64/SwitchStack.S diff --git a/EmulatorPkg/Unix/Host/AArch64/Gasket.c b/EmulatorPkg/Unix/Host= /AArch64/Gasket.c new file mode 100644 index 0000000000..69a728d408 --- /dev/null +++ b/EmulatorPkg/Unix/Host/AArch64/Gasket.c @@ -0,0 +1,50 @@ +/** @file=0D +=0D + Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>=0D + Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "Host.h"=0D +=0D +//=0D +// Reverse (UNIX to EFIAPI) gaskets=0D +//=0D +=0D +typedef=0D +UINTN=0D +(EFIAPI *CALL_BACK_1) (=0D + UINT64 Delta=0D + );=0D +=0D +UINTN=0D +ReverseGasketUint64 (=0D + UINTN CallBack,=0D + UINT64 a=0D + )=0D +{=0D + return ((CALL_BACK_1) CallBack) (a);=0D +}=0D +=0D +//=0D +// UNIX ABI to EFI ABI call=0D +//=0D +=0D +typedef=0D +UINTN=0D +(EFIAPI *CALL_BACK_2) (=0D + VOID *Context,=0D + VOID *Key=0D + );=0D +=0D +UINTN=0D +ReverseGasketUint64Uint64 (=0D + VOID *CallBack,=0D + VOID *Context,=0D + VOID *Key=0D + )=0D +{=0D + return ((CALL_BACK_2) CallBack) (Context, Key);=0D +}=0D diff --git a/EmulatorPkg/Unix/Host/AArch64/SwitchStack.S b/EmulatorPkg/Unix= /Host/AArch64/SwitchStack.S new file mode 100644 index 0000000000..6e903b94ef --- /dev/null +++ b/EmulatorPkg/Unix/Host/AArch64/SwitchStack.S @@ -0,0 +1,42 @@ +#-------------------------------------------------------------------------= -----=0D +#=0D +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>=0D +# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>= =0D +# Portions copyright (c) 2011 - 2013, ARM Limited. All rights reserved.<BR= =0D+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#-------------------------------------------------------------------------= -----=0D +=0D +.text=0D +.align 5=0D +=0D +GCC_ASM_EXPORT(PeiSwitchStacks)=0D +=0D +#/**=0D +#=0D +# This allows the caller to switch the stack and goes to the new entry po= int=0D +#=0D +# @param EntryPoint The pointer to the location to enter=0D +# @param Context Parameter to pass in=0D +# @param Context2 Parameter2 to pass in=0D +# @param NewStack New Location of the stack=0D +#=0D +# @return Nothing. Goes to the Entry Point passing in the new paramete= rs=0D +#=0D +#**/=0D +#VOID=0D +#EFIAPI=0D +#PeiSwitchStacks (=0D +# SWITCH_STACK_ENTRY_POINT EntryPoint,=0D +# VOID *Context,=0D +# VOID *Context2,=0D +# VOID *NewStack=0D +# );=0D +#=0D +ASM_PFX(PeiSwitchStacks):=0D + mov x29, #0=0D + mov x30, x0=0D + mov sp, x3=0D + mov x0, x1=0D + mov x1, x2=0D + ret=0D diff --git a/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c b/EmulatorPkg/Uni= x/Host/BerkeleyPacketFilter.c index 441f1e8d0a..f591d94f4e 100644 --- a/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c +++ b/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c @@ -972,6 +972,26 @@ EmuSnpReceive ( return EFI_SUCCESS;=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_SNP_PROTOCOL gEmuSnpProtocol =3D {=0D + EmuSnpCreateMapping,=0D + EmuSnpStart,=0D + EmuSnpStop,=0D + EmuSnpInitialize,=0D + EmuSnpReset,=0D + EmuSnpShutdown,=0D + EmuSnpReceiveFilters,=0D + EmuSnpStationAddress,=0D + EmuSnpStatistics,=0D + EmuSnpMCastIpToMac,=0D + EmuSnpNvData,=0D + EmuSnpGetStatus,=0D + EmuSnpTransmit,=0D + EmuSnpReceive=0D +};=0D +=0D +#else=0D =0D EMU_SNP_PROTOCOL gEmuSnpProtocol =3D {=0D GasketSnpCreateMapping,=0D @@ -990,6 +1010,8 @@ EMU_SNP_PROTOCOL gEmuSnpProtocol =3D { GasketSnpReceive=0D };=0D =0D +#endif=0D +=0D EFI_STATUS=0D GetInterfaceMacAddr (=0D EMU_SNP_PRIVATE *Private=0D @@ -1092,6 +1114,19 @@ EmuSnpThunkClose ( }=0D =0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D {=0D + &gEmuSnpProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + EmuSnpThunkOpen,=0D + EmuSnpThunkClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D {=0D &gEmuSnpProtocolGuid,=0D @@ -1104,3 +1139,5 @@ EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D { };=0D =0D #endif=0D +=0D +#endif=0D diff --git a/EmulatorPkg/Unix/Host/BlockIo.c b/EmulatorPkg/Unix/Host/BlockI= o.c index 18368060d5..b335db192e 100644 --- a/EmulatorPkg/Unix/Host/BlockIo.c +++ b/EmulatorPkg/Unix/Host/BlockIo.c @@ -594,6 +594,17 @@ StdDupUnicodeToAscii ( return Ascii;=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol =3D {=0D + EmuBlockIoReset,=0D + EmuBlockIoReadBlocks,=0D + EmuBlockIoWriteBlocks,=0D + EmuBlockIoFlushBlocks,=0D + EmuBlockIoCreateMapping=0D +};=0D +=0D +#else=0D =0D EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol =3D {=0D GasketEmuBlockIoReset,=0D @@ -603,6 +614,8 @@ EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol =3D { GasketEmuBlockIoCreateMapping=0D };=0D =0D +#endif=0D +=0D EFI_STATUS=0D EmuBlockIoThunkOpen (=0D IN EMU_IO_THUNK_PROTOCOL *This=0D @@ -687,7 +700,19 @@ EmuBlockIoThunkClose ( return EFI_SUCCESS;=0D }=0D =0D +#if defined(__aarch64__)=0D =0D +EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo =3D {=0D + &gEmuBlockIoProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + EmuBlockIoThunkOpen,=0D + EmuBlockIoThunkClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo =3D {=0D &gEmuBlockIoProtocolGuid,=0D @@ -699,4 +724,5 @@ EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo =3D { NULL=0D };=0D =0D +#endif=0D =0D diff --git a/EmulatorPkg/Unix/Host/EmuThunk.c b/EmulatorPkg/Unix/Host/EmuTh= unk.c index b8b0651c6a..bd78232f9c 100644 --- a/EmulatorPkg/Unix/Host/EmuThunk.c +++ b/EmulatorPkg/Unix/Host/EmuThunk.c @@ -396,6 +396,34 @@ SecGetNextProtocol ( return GetNextThunkProtocol (EmuBusDriver, Instance);=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_THUNK_PROTOCOL gEmuThunkProtocol =3D {=0D + SecWriteStdErr,=0D + SecConfigStdIn,=0D + SecWriteStdOut,=0D + SecReadStdIn,=0D + SecPollStdIn,=0D + SecMalloc,=0D + SecValloc,=0D + SecFree,=0D + SecPeCoffGetEntryPoint,=0D + SecPeCoffRelocateImageExtraAction,=0D + SecPeCoffUnloadImageExtraAction,=0D + SecEnableInterrupt,=0D + SecDisableInterrupt,=0D + QueryPerformanceFrequency,=0D + QueryPerformanceCounter,=0D + SecSleep,=0D + SecCpuSleep,=0D + SecExit,=0D + SecGetTime,=0D + SecSetTime,=0D + SecSetTimer,=0D + SecGetNextProtocol=0D +};=0D +=0D +#else=0D =0D EMU_THUNK_PROTOCOL gEmuThunkProtocol =3D {=0D GasketSecWriteStdErr,=0D @@ -422,6 +450,7 @@ EMU_THUNK_PROTOCOL gEmuThunkProtocol =3D { GasketSecGetNextProtocol=0D };=0D =0D +#endif=0D =0D VOID=0D SecInitThunkProtocol (=0D diff --git a/EmulatorPkg/Unix/Host/Host.c b/EmulatorPkg/Unix/Host/Host.c index b4e5510613..bba6282738 100644 --- a/EmulatorPkg/Unix/Host/Host.c +++ b/EmulatorPkg/Unix/Host/Host.c @@ -12,17 +12,49 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define MAP_ANONYMOUS MAP_ANON=0D #endif=0D =0D +EFI_STATUS=0D +SecUnixPeiAutoScan (=0D + IN UINTN Index,=0D + OUT EFI_PHYSICAL_ADDRESS *MemoryBase,=0D + OUT UINT64 *MemorySize=0D + );=0D +=0D +EFI_STATUS=0D +SecUnixFdAddress (=0D + IN UINTN Index,=0D + IN OUT EFI_PHYSICAL_ADDRESS *FdBase,=0D + IN OUT UINT64 *FdSize,=0D + IN OUT EFI_PHYSICAL_ADDRESS *FixUp=0D + );=0D +=0D +VOID *=0D +SecEmuThunkAddress (=0D + VOID=0D + );=0D +=0D =0D //=0D // Globals=0D //=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_THUNK_PPI mSecEmuThunkPpi =3D {=0D + SecUnixPeiAutoScan,=0D + SecUnixFdAddress,=0D + SecEmuThunkAddress=0D +};=0D +=0D +#else=0D +=0D EMU_THUNK_PPI mSecEmuThunkPpi =3D {=0D GasketSecUnixPeiAutoScan,=0D GasketSecUnixFdAddress,=0D GasketSecEmuThunkAddress=0D };=0D =0D +#endif=0D +=0D char *gGdbWorkingFileName =3D NULL;=0D unsigned int mScriptSymbolChangesCount =3D 0;=0D =0D diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf index c479d2b7d0..43cb55aa21 100644 --- a/EmulatorPkg/Unix/Host/Host.inf +++ b/EmulatorPkg/Unix/Host/Host.inf @@ -20,7 +20,7 @@ #=0D # The following information is for reference only and not required by the = build tools.=0D #=0D -# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D +# VALID_ARCHITECTURES =3D IA32 X64 AARCH64 EBC=0D #=0D =0D [Sources]=0D @@ -42,6 +42,9 @@ Ia32/Gasket.S # enforce 16-byte stack alignment for Mac OS X=0D Ia32/SwitchStack.c=0D =0D +[Sources.AARCH64]=0D + AArch64/Gasket.c=0D + AArch64/SwitchStack.S=0D =0D [Packages]=0D MdePkg/MdePkg.dec=0D diff --git a/EmulatorPkg/Unix/Host/LinuxPacketFilter.c b/EmulatorPkg/Unix/H= ost/LinuxPacketFilter.c index 2b772ab884..9c696a8774 100644 --- a/EmulatorPkg/Unix/Host/LinuxPacketFilter.c +++ b/EmulatorPkg/Unix/Host/LinuxPacketFilter.c @@ -518,6 +518,27 @@ EmuSnpReceive ( }=0D =0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_SNP_PROTOCOL gEmuSnpProtocol =3D {=0D + EmuSnpCreateMapping,=0D + EmuSnpStart,=0D + EmuSnpStop,=0D + EmuSnpInitialize,=0D + EmuSnpReset,=0D + EmuSnpShutdown,=0D + EmuSnpReceiveFilters,=0D + EmuSnpStationAddress,=0D + EmuSnpStatistics,=0D + EmuSnpMCastIpToMac,=0D + EmuSnpNvData,=0D + EmuSnpGetStatus,=0D + EmuSnpTransmit,=0D + EmuSnpReceive=0D +};=0D +=0D +#else=0D +=0D EMU_SNP_PROTOCOL gEmuSnpProtocol =3D {=0D GasketSnpCreateMapping,=0D GasketSnpStart,=0D @@ -535,6 +556,8 @@ EMU_SNP_PROTOCOL gEmuSnpProtocol =3D { GasketSnpReceive=0D };=0D =0D +#endif=0D +=0D EFI_STATUS=0D EmuSnpThunkOpen (=0D IN EMU_IO_THUNK_PROTOCOL *This=0D @@ -584,6 +607,19 @@ EmuSnpThunkClose ( }=0D =0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D {=0D + &gEmuSnpProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + EmuSnpThunkOpen,=0D + EmuSnpThunkClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D {=0D &gEmuSnpProtocolGuid,=0D @@ -596,3 +632,5 @@ EMU_IO_THUNK_PROTOCOL gSnpThunkIo =3D { };=0D =0D #endif=0D +=0D +#endif=0D diff --git a/EmulatorPkg/Unix/Host/PosixFileSystem.c b/EmulatorPkg/Unix/Hos= t/PosixFileSystem.c index 0a618abcd8..4676f2f933 100644 --- a/EmulatorPkg/Unix/Host/PosixFileSystem.c +++ b/EmulatorPkg/Unix/Host/PosixFileSystem.c @@ -53,6 +53,51 @@ typedef struct { EMU_EFI_FILE_PRIVATE_SIGNATURE \=0D )=0D =0D +EFI_STATUS=0D +PosixFileOpen (=0D + IN EFI_FILE_PROTOCOL *This,=0D + OUT EFI_FILE_PROTOCOL **NewHandle,=0D + IN CHAR16 *FileName,=0D + IN UINT64 OpenMode,=0D + IN UINT64 Attributes=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileCLose (=0D + IN EFI_FILE_PROTOCOL *This=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileDelete (=0D + IN EFI_FILE_PROTOCOL *This=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileRead (=0D + IN EFI_FILE_PROTOCOL *This,=0D + IN OUT UINTN *BufferSize,=0D + OUT VOID *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileWrite (=0D + IN EFI_FILE_PROTOCOL *This,=0D + IN OUT UINTN *BufferSize,=0D + IN VOID *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileGetPossition (=0D + IN EFI_FILE_PROTOCOL *This,=0D + OUT UINT64 *Position=0D + );=0D +=0D +EFI_STATUS=0D +PosixFileSetPossition (=0D + IN EFI_FILE_PROTOCOL *This,=0D + IN UINT64 Position=0D + );=0D +=0D EFI_STATUS=0D PosixFileGetInfo (=0D IN EFI_FILE_PROTOCOL *This,=0D @@ -69,6 +114,39 @@ PosixFileSetInfo ( IN VOID *Buffer=0D );=0D =0D +EFI_STATUS=0D +PosixFileFlush (=0D + IN EFI_FILE_PROTOCOL *This=0D + );=0D +=0D +EFI_STATUS=0D +PosixOpenVolume (=0D + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,=0D + OUT EFI_FILE_PROTOCOL **Root=0D + );=0D +=0D +#if defined(__aarch64__)=0D +=0D +EFI_FILE_PROTOCOL gPosixFileProtocol =3D {=0D + EFI_FILE_REVISION,=0D + PosixFileOpen,=0D + PosixFileCLose,=0D + PosixFileDelete,=0D + PosixFileRead,=0D + PosixFileWrite,=0D + PosixFileGetPossition,=0D + PosixFileSetPossition,=0D + PosixFileGetInfo,=0D + PosixFileSetInfo,=0D + PosixFileFlush=0D +};=0D +=0D +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gPosixFileSystemProtocol =3D {=0D + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,=0D + PosixOpenVolume,=0D +};=0D +=0D +#else=0D =0D EFI_FILE_PROTOCOL gPosixFileProtocol =3D {=0D EFI_FILE_REVISION,=0D @@ -89,6 +167,7 @@ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gPosixFileSystemProtocol= =3D { GasketPosixOpenVolume,=0D };=0D =0D +#endif=0D =0D /**=0D Open the root directory on a volume.=0D @@ -1573,6 +1652,19 @@ PosixFileSystmeThunkClose ( return EFI_SUCCESS;=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo =3D {=0D + &gEfiSimpleFileSystemProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + PosixFileSystmeThunkOpen,=0D + PosixFileSystmeThunkClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo =3D {=0D &gEfiSimpleFileSystemProtocolGuid,=0D @@ -1584,4 +1676,4 @@ EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo =3D { NULL=0D };=0D =0D -=0D +#endif=0D diff --git a/EmulatorPkg/Unix/Host/Pthreads.c b/EmulatorPkg/Unix/Host/Pthre= ads.c index 025687c356..3613e4cf60 100644 --- a/EmulatorPkg/Unix/Host/Pthreads.c +++ b/EmulatorPkg/Unix/Host/Pthreads.c @@ -173,6 +173,20 @@ PthreadSelf ( return (UINTN)pthread_self ();=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_THREAD_THUNK_PROTOCOL gPthreadThunk =3D {=0D + PthreadMutexLock,=0D + PthreadMutexUnLock,=0D + PthreadMutexTryLock,=0D + PthreadMutexInit,=0D + PthreadMutexDestroy,=0D + PthreadCreate,=0D + PthreadExit,=0D + PthreadSelf=0D +};=0D +=0D +#else=0D =0D EMU_THREAD_THUNK_PROTOCOL gPthreadThunk =3D {=0D GasketPthreadMutexLock,=0D @@ -185,6 +199,7 @@ EMU_THREAD_THUNK_PROTOCOL gPthreadThunk =3D { GasketPthreadSelf=0D };=0D =0D +#endif=0D =0D EFI_STATUS=0D PthreadOpen (=0D @@ -215,6 +230,19 @@ PthreadClose ( return EFI_SUCCESS;=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_IO_THUNK_PROTOCOL gPthreadThunkIo =3D {=0D + &gEmuThreadThunkProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + PthreadOpen,=0D + PthreadClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gPthreadThunkIo =3D {=0D &gEmuThreadThunkProtocolGuid,=0D @@ -226,4 +254,4 @@ EMU_IO_THUNK_PROTOCOL gPthreadThunkIo =3D { NULL=0D };=0D =0D -=0D +#endif=0D diff --git a/EmulatorPkg/Unix/Host/X11GraphicsWindow.c b/EmulatorPkg/Unix/H= ost/X11GraphicsWindow.c index 5325a0e35b..cff8a6f7b9 100644 --- a/EmulatorPkg/Unix/Host/X11GraphicsWindow.c +++ b/EmulatorPkg/Unix/Host/X11GraphicsWindow.c @@ -918,6 +918,16 @@ X11GraphicsWindowOpen ( return EFI_OUT_OF_RESOURCES;=0D }=0D =0D +#if defined(__aarch64__)=0D + Drv->GraphicsIo.Size =3D X11Size;=0D + Drv->GraphicsIo.CheckKey =3D X11CheckKey;=0D + Drv->GraphicsIo.GetKey =3D X11GetKey;=0D + Drv->GraphicsIo.KeySetState =3D X11KeySetState;=0D + Drv->GraphicsIo.RegisterKeyNotify =3D X11RegisterKeyNotify;=0D + Drv->GraphicsIo.Blt =3D X11Blt;=0D + Drv->GraphicsIo.CheckPointer =3D X11CheckPointer;=0D + Drv->GraphicsIo.GetPointerState =3D X11GetPointerState;=0D +#else=0D Drv->GraphicsIo.Size =3D GasketX11Size;=0D Drv->GraphicsIo.CheckKey =3D GasketX11CheckKey;=0D Drv->GraphicsIo.GetKey =3D GasketX11GetKey;=0D @@ -926,6 +936,7 @@ X11GraphicsWindowOpen ( Drv->GraphicsIo.Blt =3D GasketX11Blt;=0D Drv->GraphicsIo.CheckPointer =3D GasketX11CheckPointer;=0D Drv->GraphicsIo.GetPointerState =3D GasketX11GetPointerState;=0D +#endif=0D =0D =0D Drv->key_count =3D 0;=0D @@ -1008,6 +1019,19 @@ X11GraphicsWindowClose ( return EFI_SUCCESS;=0D }=0D =0D +#if defined(__aarch64__)=0D +=0D +EMU_IO_THUNK_PROTOCOL gX11ThunkIo =3D {=0D + &gEmuGraphicsWindowProtocolGuid,=0D + NULL,=0D + NULL,=0D + 0,=0D + X11GraphicsWindowOpen,=0D + X11GraphicsWindowClose,=0D + NULL=0D +};=0D +=0D +#else=0D =0D EMU_IO_THUNK_PROTOCOL gX11ThunkIo =3D {=0D &gEmuGraphicsWindowProtocolGuid,=0D @@ -1019,4 +1043,4 @@ EMU_IO_THUNK_PROTOCOL gX11ThunkIo =3D { NULL=0D };=0D =0D -=0D +#endif=0D --=20 2.33.0 |
|
[RFC PATCH 2/4] EmulatorPkg/Sec: Add AArch64 support
Akira Moroo
This commit adds AArch64 support to EmulatorPkg/Sec. The architecture
specific part is switching stack from temporary to permanent. Signed-off-by: Akira Moroo <retrage01@...> --- EmulatorPkg/Sec/AArch64/SwitchRam.S | 22 +++++++++++ EmulatorPkg/Sec/AArch64/TempRam.c | 58 +++++++++++++++++++++++++++++ EmulatorPkg/Sec/Sec.inf | 4 ++ 3 files changed, 84 insertions(+) create mode 100644 EmulatorPkg/Sec/AArch64/SwitchRam.S create mode 100644 EmulatorPkg/Sec/AArch64/TempRam.c diff --git a/EmulatorPkg/Sec/AArch64/SwitchRam.S b/EmulatorPkg/Sec/AArch64/= SwitchRam.S new file mode 100644 index 0000000000..9ec8ddd627 --- /dev/null +++ b/EmulatorPkg/Sec/AArch64/SwitchRam.S @@ -0,0 +1,22 @@ +#-------------------------------------------------------------------------= -----=0D +#=0D +# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>=0D +# Portions copyright (c) 2011, Apple Inc. All rights reserved.=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#-------------------------------------------------------------------------= -----=0D +=0D +=0D +// VOID=0D +// EFIAPI=0D +// SecSwitchStack (=0D +// VOID *StackDelta=0D +// )=0D +//=0D +ASM_GLOBAL ASM_PFX(SecSwitchStack)=0D +ASM_PFX(SecSwitchStack):=0D + mov x1, sp=0D + add x1, x0, x1=0D + mov sp, x1=0D + ret=0D +=0D diff --git a/EmulatorPkg/Sec/AArch64/TempRam.c b/EmulatorPkg/Sec/AArch64/Te= mpRam.c new file mode 100644 index 0000000000..cce1dc559a --- /dev/null +++ b/EmulatorPkg/Sec/AArch64/TempRam.c @@ -0,0 +1,58 @@ +/*++ @file=0D + Temp RAM PPI=0D +=0D +Copyright (c) 2011, Apple Inc. All rights reserved.<BR>=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include <PiPei.h>=0D +#include <Library/DebugLib.h>=0D +#include <Library/BaseMemoryLib.h>=0D +=0D +#include <Ppi/TemporaryRamSupport.h>=0D +=0D +VOID=0D +EFIAPI=0D +SecSwitchStack (=0D + VOID *StackDelta=0D + );=0D +=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +SecTemporaryRamSupport (=0D + IN CONST EFI_PEI_SERVICES **PeiServices,=0D + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,=0D + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,=0D + IN UINTN CopySize=0D + )=0D +{=0D + //=0D + // Migrate the whole temporary memory to permanent memory.=0D + //=0D + CopyMem (=0D + (VOID*)(UINTN)PermanentMemoryBase,=0D + (VOID*)(UINTN)TemporaryMemoryBase,=0D + CopySize=0D + );=0D +=0D + //=0D + // SecSwitchStack function must be invoked after the memory migration=0D + // immediately, also we need fixup the stack change caused by new call i= nto=0D + // permanent memory.=0D + //=0D + SecSwitchStack ((VOID *)(PermanentMemoryBase - TemporaryMemoryBase));=0D +=0D + //=0D + // We need *not* fix the return address because currently,=0D + // The PeiCore is executed in flash.=0D + //=0D +=0D + //=0D + // Simulate to invalid temporary memory, terminate temporary memory=0D + //=0D + ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);=0D +=0D + return EFI_SUCCESS;=0D +}=0D diff --git a/EmulatorPkg/Sec/Sec.inf b/EmulatorPkg/Sec/Sec.inf index 2f9e3d4780..83248fbaca 100644 --- a/EmulatorPkg/Sec/Sec.inf +++ b/EmulatorPkg/Sec/Sec.inf @@ -30,6 +30,10 @@ Ia32/SwitchRam.asm=0D Ia32/SwitchRam.S=0D =0D +[Sources.AARCH64]=0D + AArch64/TempRam.c=0D + AArch64/SwitchRam.S=0D +=0D [Packages]=0D MdePkg/MdePkg.dec=0D EmulatorPkg/EmulatorPkg.dec=0D --=20 2.33.0 |
|
[RFC PATCH 1/4] EmulatorPkg/Unix/Host: Fix typo
Akira Moroo
The function name should be `SecPeCoffUnloadImageExtraAction`.
Signed-off-by: Akira Moroo <retrage01@...> --- EmulatorPkg/Unix/Host/Host.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EmulatorPkg/Unix/Host/Host.h b/EmulatorPkg/Unix/Host/Host.h index 9791cf8c37..3841a91db8 100644 --- a/EmulatorPkg/Unix/Host/Host.h +++ b/EmulatorPkg/Unix/Host/Host.h @@ -292,8 +292,8 @@ SecPeCoffRelocateImageExtraAction ( =0D VOID=0D EFIAPI=0D -SecPeCoffLoaderUnloadImageExtraAction (=0D - IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext=0D +SecPeCoffUnloadImageExtraAction (=0D + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext=0D );=0D =0D =0D --=20 2.33.0 |
|
[RFC PATCH 0/4] EmulatorPkg AArch64 Linux support
Akira Moroo
This series of patches proposes adding AArch64 Linux host support for
EmulatorPkg. The main difference from IA32/X64 is that it does not need to convert calling conventions between EFI environment and the host. It is enough just directly registering the host side functions to the EmulatorPkg provided UEFI protocols. I tested this feature on the latest Ubuntu 20.04 with both CLANG38 and GCC5 toolchains. The patch 1/4 is a trivial typo fix that are required for the 3/4 patch. The 2/4 adds AArch64 specific stack switch code for EmulatorPkg/Sec. The 3/4 changes EmulatorPkg/Unix/Host to support AArch64. The 4/4 introduces EmulatorPkg AArch64 Linux host build support. Akira Moroo (4): EmulatorPkg/Unix/Host: Fix typo EmulatorPkg/Sec: Add AArch64 support EmulatorPkg/Unix/Host: Add AArch64 support EmulatorPkg: Add AArch64 Unix host build support EmulatorPkg/EmulatorPkg.dsc | 15 +++- EmulatorPkg/Readme.md | 8 ++ EmulatorPkg/Sec/AArch64/SwitchRam.S | 22 +++++ EmulatorPkg/Sec/AArch64/TempRam.c | 58 ++++++++++++ EmulatorPkg/Sec/Sec.inf | 4 + EmulatorPkg/Unix/Host/AArch64/Gasket.c | 50 +++++++++++ EmulatorPkg/Unix/Host/AArch64/SwitchStack.S | 42 +++++++++ EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c | 37 ++++++++ EmulatorPkg/Unix/Host/BlockIo.c | 26 ++++++ EmulatorPkg/Unix/Host/EmuThunk.c | 29 ++++++ EmulatorPkg/Unix/Host/Host.c | 32 +++++++ EmulatorPkg/Unix/Host/Host.h | 4 +- EmulatorPkg/Unix/Host/Host.inf | 10 ++- EmulatorPkg/Unix/Host/LinuxPacketFilter.c | 38 ++++++++ EmulatorPkg/Unix/Host/PosixFileSystem.c | 94 +++++++++++++++++++- EmulatorPkg/Unix/Host/Pthreads.c | 30 ++++++- EmulatorPkg/Unix/Host/X11GraphicsWindow.c | 26 +++++- EmulatorPkg/build.sh | 8 ++ 18 files changed, 524 insertions(+), 9 deletions(-) create mode 100644 EmulatorPkg/Sec/AArch64/SwitchRam.S create mode 100644 EmulatorPkg/Sec/AArch64/TempRam.c create mode 100644 EmulatorPkg/Unix/Host/AArch64/Gasket.c create mode 100644 EmulatorPkg/Unix/Host/AArch64/SwitchStack.S -- 2.33.0 |
|
Re: [EXTERNAL] [edk2-devel] [PATCH v1 1/1] SecurityPkg/Library: Add Tpm2NvUndefineSpaceSpecial to Tpm2CommandLib
Yao, Jiewen
Hey Is that any update for this patch?
I did not see the v2 patch. Just want to ensure I did not miss that by mistake.
Thank you Yao Jiewen
From: Bret Barkelew <Bret.Barkelew@...>
Sent: Friday, August 13, 2021 11:22 AM To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io; gaoliming@...; bret@...; Kinney, Michael D <michael.d.kinney@...> Cc: Wang, Jian J <jian.j.wang@...>; Zhang, Qi1 <qi1.zhang@...>; Kumar, Rahul1 <rahul1.kumar@...> Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v1 1/1] SecurityPkg/Library: Add Tpm2NvUndefineSpaceSpecial to Tpm2CommandLib
Thanks, Jiewen! I’ll make those changes!
- Bret From: Yao, Jiewen <jiewen.yao@...>
Hi Bret Since it took much long time to get ECC feedback than I expected, I would give feedback on code while we are waiting.
1) Please confirm how you test the code, such as Microsoft platform ? 2) Please remove “+} // Tpm2NvUndefineSpaceSpecial()” at the end of the function. We do not use that style in other code. 3) Please copy the definition from TPM spec “This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE SET” to the function header description. The current one “This command removes an index from the TPM.” is for TPM2_NV_UndefineSpace instead of TPM2_NV_UndefineSpaceSpecial.
Since above comment does not impact any function, I would like to give RB.
With about change, reviewed-by: Jiewen Yao <Jiewen.yao@...>
Thank you Yao Jiewen
From: Bret Barkelew via groups.io
Note, even though this keeps with the style of the rest of the file, it breaks ECC:
PROGRESS - --Running SecurityPkg: EccCheck Test NO-TARGET -- ERROR - ERROR - ERROR - EFI coding style error ERROR - *Error code: 8001 ERROR - *Only capital letters are allowed to be used for #define declarations ERROR - *file: //home/vsts/work/1/s/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c ERROR - *Line number: 27 ERROR - *The #define name [RC_NV_UndefineSpaceSpecial_nvIndex] does no
Thoughts?
- Bret
From: Bret Barkelew via groups.io
Used to provision and maintain certain HW-defined NV spaces.
|
|
Re: [PATCH] Define FIT 4 record
Chaganty, Rangasai V
HI Michael, The actual changes are fine. A couple of comments on the patch format.
[Repo Name: [Optional] Patch Version# #/total #] PackageName: <One line summary of the change>
You can get more details on these guidelines here.
Regards, Sai
From: Holland, Michael <michael.holland@...>
Sent: Tuesday, September 28, 2021 7:15 PM To: devel@edk2.groups.io Cc: Chaganty, Rangasai V <rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...> Subject: [PATCH] Define FIT 4 record
|
|
Re: [PATCH v7 1/1] MdePkg/BaseLib: Add QuickSort function on BaseLib
Marvin Häuser
Hey all,
toggle quoted message
Show quoted text
I also don't think it makes much logical sense. They are distinct APIs in separate libraries that happen to take a function with the same prototype. I think the patches look good now, thanks! Best regards, Marvin On 08/10/2021 17:46, Michael D Kinney wrote:
Hi Liming, |
|
Re: [PATCH v3 00/21] Create a SSDT CPU topology generator
Sami Mujawar
Merged as 30400318a278..769e63999ff5
Thanks. Regards, Sami Mujawar On 08/10/2021 03:46 PM, Pierre.Gondois@... wrote: From: Pierre Gondois <Pierre.Gondois@...>IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. |
|
Re: [PATCH v1] ShellPkg: Update Acpiview HMAT parser to ACPI spec version
6.4
Sami Mujawar
Merged as 5ece2ad36caa..30400318a278 Thanks. Regards, Sami Mujawar On 08/10/2021 06:59 AM, Gao, Zhichao wrote:
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. |
|
Re: [PATCH v7 1/1] MdePkg/BaseLib: Add QuickSort function on BaseLib
Michael D Kinney
Hi Liming,
toggle quoted message
Show quoted text
In general it is not a good idea to include a library include file from another library include file. This becomes a hidden dependency. Mike -----Original Message----- |
|
Re: [Patch V2 1/1] BaseTools: Change RealPath to AbsPath
Bob Feng
Hi Christine,
toggle quoted message
Show quoted text
For the case that a directory is a symbol link, we should use os.path.realpath. if os.path.islink(Dirname): - Dirname = os.path.realpath(Dirname) + Dirname = os.path.abspath(Dirname) Thanks, Bob -----Original Message-----
From: Chen, Christine <yuwei.chen@...> Sent: Wednesday, September 29, 2021 4:44 PM To: devel@edk2.groups.io Cc: Feng, Bob C <bob.c.feng@...>; Liming Gao <gaoliming@...> Subject: [Patch V2 1/1] BaseTools: Change RealPath to AbsPath Currently the realpath is used when parse modules, which shows the path with a drive letter in build log. In Windows 'subst' comand is used to associates a path with a drive letter, when use the mapped drive letter for build, with realpath function the build log will have different disk letter info which will cause confusion. In this situation, if use adspath function to show the path info, it will keep same letter with the mapped drive letter, which avoids confusion. This patch modifies the realpath to abspath. Cc: Bob Feng <bob.c.feng@...> Cc: Liming Gao <gaoliming@...> Signed-off-by: Yuwei Chen <yuwei.chen@...> --- .gitignore | 1 + BaseTools/Source/Python/Ecc/Check.py | 2 +- BaseTools/Source/Python/Ecc/EccMain.py | 4 ++-- BaseTools/Source/Python/Ecc/c.py | 2 +- BaseTools/Source/Python/GenFds/FfsInfStatement.py | 4 ++-- BaseTools/Source/Python/GenFds/GenFds.py | 6 +++--- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 1dd30c141066..41471df06ba8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Build/ __pycache__/ tags/ .vscode/ +/bin/ diff --git a/BaseTools/Source/Python/Ecc/Check.py b/BaseTools/Source/Python/Ecc/Check.py index 33060db5f27a..ba04e6e0619d 100644 --- a/BaseTools/Source/Python/Ecc/Check.py +++ b/BaseTools/Source/Python/Ecc/Check.py @@ -332,7 +332,7 @@ class Check(object): for Dir in Dirnames: Dirname = os.path.join(Dirpath, Dir) if os.path.islink(Dirname): - Dirname = os.path.realpath(Dirname) + Dirname = os.path.abspath(Dirname) if os.path.isdir(Dirname): # symlinks to directories are treated as directories Dirnames.remove(Dir) diff --git a/BaseTools/Source/Python/Ecc/EccMain.py b/BaseTools/Source/Python/Ecc/EccMain.py index 72edbea3b883..e7d44f57f1b4 100644 --- a/BaseTools/Source/Python/Ecc/EccMain.py +++ b/BaseTools/Source/Python/Ecc/EccMain.py @@ -105,7 +105,7 @@ class Ecc(object): def InitDefaultConfigIni(self): paths = map(lambda p: os.path.join(p, 'Ecc', 'config.ini'), sys.path) - paths = (os.path.realpath('config.ini'),) + tuple(paths) + paths = (os.path.abspath('config.ini'),) + tuple(paths) for path in paths: if os.path.exists(path): self.ConfigFile = path @@ -183,7 +183,7 @@ class Ecc(object): for Dir in Dirs: Dirname = os.path.join(Root, Dir) if os.path.islink(Dirname): - Dirname = os.path.realpath(Dirname) + Dirname = os.path.abspath(Dirname) if os.path.isdir(Dirname): # symlinks to directories are treated as directories Dirs.remove(Dir) diff --git a/BaseTools/Source/Python/Ecc/c.py b/BaseTools/Source/Python/Ecc/c.py index 4a82e5e76003..313d6b088c12 100644 --- a/BaseTools/Source/Python/Ecc/c.py +++ b/BaseTools/Source/Python/Ecc/c.py @@ -508,7 +508,7 @@ def CollectSourceCodeDataIntoDB(RootDir): for Dir in dirnames: Dirname = os.path.join(dirpath, Dir) if os.path.islink(Dirname): - Dirname = os.path.realpath(Dirname) + Dirname = os.path.abspath(Dirname) if os.path.isdir(Dirname): # symlinks to directories are treated as directories dirnames.remove(Dir) diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py index 20573ca28d2f..568efb6d7685 100644 --- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -707,8 +707,8 @@ class FfsInfStatement(FfsInfStatementClassObject): FileName, 'DEBUG' ) - OutputPath = os.path.realpath(OutputPath) - DebugPath = os.path.realpath(DebugPath) + OutputPath = os.path.abspath(OutputPath) + DebugPath = os.path.abspath(DebugPath) return OutputPath, DebugPath ## __GenSimpleFileSection__() method diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py index ae3e776a5540..7f266e163c73 100644 --- a/BaseTools/Source/Python/GenFds/GenFds.py +++ b/BaseTools/Source/Python/GenFds/GenFds.py @@ -153,7 +153,7 @@ def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None): FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename) if FdfFilename[0:2] == '..': - FdfFilename = os.path.realpath(FdfFilename) + FdfFilename = os.path.abspath(FdfFilename) if not os.path.isabs(FdfFilename): FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename) if not os.path.exists(FdfFilename): @@ -175,7 +175,7 @@ def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None): ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform) if ActivePlatform[0:2] == '..': - ActivePlatform = os.path.realpath(ActivePlatform) + ActivePlatform = os.path.abspath(ActivePlatform) if not os.path.isabs (ActivePlatform): ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform) @@ -299,7 +299,7 @@ def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None): for Key in GenFdsGlobalVariable.OutputDirDict: OutputDir = GenFdsGlobalVariable.OutputDirDict[Key] if OutputDir[0:2] == '..': - OutputDir = os.path.realpath(OutputDir) + OutputDir = os.path.abspath(OutputDir) if OutputDir[1] != ':': OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir) -- 2.26.1.windows.1 |
|
Re: [RFC] [PATCH 0/2] Proposal to add EFI_MP_SERVICES_PROTOCOL support for AARCH64
Ard Biesheuvel
On Thu, 7 Oct 2021 at 13:02, Leif Lindholm <leif@...> wrote:
Ok, so that doesn't look as bad as I thought. But we'll have to be more strict than other arches: even EFI services and protocols that are marked as safe for execution under this MP protocol are likely to explode if they rely on CopyMem() or SetMem() for in/outputs that are not a multiple of 8 bytes in case the platform uses the BaseMemoryLibOptDxe flavour of this library, since it relies heavily on deliberately misaligned loads and stores. |
|
[PATCH v3 21/21] DynamicTablesPkg: SSDT CPU topology and LPI state generator
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
In the GIC interrupt model, logical processors are required to have a Processor Device object in the DSDT and must convey each processor's GIC information to the OS using the GICC structure. Additionally, _LPI objects may be needed as they provide a method to describe Low Power Idle states that defines the local power states for each node in a hierarchical processor topology. Therefore, add support to generate the CPU topology and the LPI state information in an SSDT table. Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- DynamicTablesPkg/DynamicTables.dsc.inc | 6 + DynamicTablesPkg/Include/AcpiTableGenerator.h | 7 +- .../SsdtCpuTopologyGenerator.c | 1228 +++++++++++++++++ .../SsdtCpuTopologyGenerator.h | 134 ++ .../SsdtCpuTopologyLibArm.inf | 33 + 5 files changed, 1407 insertions(+), 1 deletion(-) create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index ed221d1681eb..292215c39456 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -37,6 +37,9 @@ [Components.common] DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf + # AML Codegen + DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf + # # Dynamic Table Factory Dxe # @@ -56,6 +59,9 @@ [Components.common] # AML Fixup NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf + + # AML Codegen + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf } # diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h index 352331d6dc95..45c808ba740d 100644 --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR> + Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent @@ -63,6 +63,10 @@ The Dynamic Tables Framework implements the following ACPI table generators: The SSDT CMN-600 generator collates the CMN-600 information from the Configuration Manager and patches the SSDT CMN-600 template to build the SSDT CMN-600 table. + - SSDT Cpu-Topology: + The SSDT Cpu-Topology generator collates the cpu and LPI + information from the Configuration Manager and generates a + SSDT table describing the CPU hierarchy. */ /** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID. @@ -88,6 +92,7 @@ typedef enum StdAcpiTableId { EStdAcpiTableIdSrat, ///< SRAT Generator EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator + EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology EStdAcpiTableIdMax } ESTD_ACPI_TABLE_ID; diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c new file mode 100644 index 000000000000..3f6cef3ba555 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c @@ -0,0 +1,1228 @@ +/** @file + SSDT Cpu Topology Table Generator. + + Copyright (c) 2021, Arm Limited. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors +**/ + +#include <Library/AcpiLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Protocol/AcpiTable.h> + +// Module specific include files. +#include <AcpiTableGenerator.h> +#include <ConfigurationManagerObject.h> +#include <ConfigurationManagerHelper.h> +#include <Library/AcpiHelperLib.h> +#include <Library/TableHelperLib.h> +#include <Library/AmlLib/AmlLib.h> +#include <Protocol/ConfigurationManagerProtocol.h> + +#include "SsdtCpuTopologyGenerator.h" + +/** ARM standard SSDT Cpu Topology Table Generator. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArmObjGicCInfo + - EArmObjProcHierarchyInfo (OPTIONAL) along with + - EArmObjCmRef (OPTIONAL) + - EArmObjLpiInfo (OPTIONAL) +*/ + +/** This macro expands to a function that retrieves the GIC + CPU interface Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjGicCInfo, + CM_ARM_GICC_INFO + ); + +/** + This macro expands to a function that retrieves the Processor Hierarchy + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjProcHierarchyInfo, + CM_ARM_PROC_HIERARCHY_INFO + ); + +/** + This macro expands to a function that retrieves the cross-CM-object- + reference information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjCmRef, + CM_ARM_OBJ_REF + ); + +/** + This macro expands to a function that retrieves the Lpi + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjLpiInfo, + CM_ARM_LPI_INFO + ); + +/** Initialize the TokenTable. + + One entry should be allocated for each CM_ARM_PROC_HIERARCHY_INFO + structure of the platform. The TokenTable allows to have a mapping: + Index <-> CM_OBJECT_TOKEN (to CM_ARM_LPI_INFO structures). + + There will always be less sets of Lpi states (CM_ARM_OBJ_REF) + than the number of cpus/clusters (CM_ARM_PROC_HIERARCHY_INFO). + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] Count Number of entries to allocate in the TokenTable. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +TokenTableInitialize ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN UINT32 Count + ) +{ + CM_OBJECT_TOKEN * Table; + + if ((Generator == NULL) || + (Count == 0) || + (Count >= MAX_NODE_COUNT)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Table = AllocateZeroPool (sizeof (CM_OBJECT_TOKEN) * Count); + if (Table == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Generator->TokenTable.Table = Table; + + return EFI_SUCCESS; +} + +/** Free the TokenTable. + + @param [in] Generator The SSDT Cpu Topology generator. +**/ +STATIC +VOID +EFIAPI +TokenTableFree ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator + ) +{ + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + + if (Generator->TokenTable.Table != NULL) { + FreePool (Generator->TokenTable.Table); + } +} + +/** Add a new entry to the TokenTable and return its index. + + If an entry with Token is already available in the table, + return its index without adding a new entry. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] Token New Token entry to add. + + @retval The index of the token entry in the TokenTable. +**/ +STATIC +UINT32 +EFIAPI +TokenTableAdd ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CM_OBJECT_TOKEN Token + ) +{ + CM_OBJECT_TOKEN * Table; + UINT32 Index; + UINT32 LastIndex; + + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + + Table = Generator->TokenTable.Table; + LastIndex = Generator->TokenTable.LastIndex; + + // Search if there is already an entry with this Token. + for (Index = 0; Index < LastIndex; Index++) { + if (Table[Index] == Token) { + return Index; + } + } + + ASSERT (LastIndex < MAX_NODE_COUNT); + ASSERT (LastIndex < Generator->ProcNodeCount); + + // If no, create a new entry. + Table[LastIndex] = Token; + + return Generator->TokenTable.LastIndex++; +} + +/** Write a string 'Xxxx\0' in AslName (5 bytes long), + with 'X' being the leading char of the name, and + with 'xxx' being Value in hexadecimal. + + As 'xxx' in hexadecimal represents a number on 12 bits, + we have Value < (1 << 12). + + @param [in] LeadChar Leading char of the name. + @param [in] Value Hex value of the name. + Must be lower than (2 << 12). + @param [in, out] AslName Pointer to write the 'Xxxx' string to. + Must be at least 5 bytes long. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +WriteAslName ( + IN CHAR8 LeadChar, + IN UINT32 Value, + IN OUT CHAR8 * AslName + ) +{ + UINT8 Index; + + if ((Value >= MAX_NODE_COUNT) || + (AslName == NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + AslName[0] = LeadChar; + AslName[AML_NAME_SEG_SIZE] = '\0'; + + for (Index = 0; Index < AML_NAME_SEG_SIZE - 1; Index++) { + AslName[AML_NAME_SEG_SIZE - Index - 1] = + AsciiFromHex (((Value >> (4 * Index)) & 0xF)); + } + + return EFI_SUCCESS; +} + +/** Create and add an _LPI method to Cpu/Cluster Node. + + For instance, transform an AML node from: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + To: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + Method (_LPI, 0, NotSerialized) + { + Return (\_SB.L003) + } + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO describing + the Cpu. + @param [in] Node Node to which the _LPI method is + attached. Can represent a Cpu or a + Cluster. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlLpiMethod ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CM_ARM_PROC_HIERARCHY_INFO * ProcHierarchyNodeInfo, + IN AML_OBJECT_NODE_HANDLE * Node + ) +{ + EFI_STATUS Status; + UINT32 TokenIndex; + CHAR8 AslName[SB_SCOPE_PREFIX_SIZE + AML_NAME_SEG_SIZE]; + + ASSERT (Generator != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN); + ASSERT (Node != NULL); + + TokenIndex = TokenTableAdd (Generator, ProcHierarchyNodeInfo->LpiToken); + + CopyMem (AslName, SB_SCOPE_PREFIX, SB_SCOPE_PREFIX_SIZE); + + Status = WriteAslName ( + 'L', + TokenIndex, + AslName + SB_SCOPE_PREFIX_SIZE - 1 + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: + // Method (_LPI, 0) { + // Return ([AslName]) + // } + Status = AmlCodeGenMethodRetNameString ( + "_LPI", + AslName, + 0, + FALSE, + 0, + Node, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + return Status; +} + +/** Generate all the Lpi states under the '_SB' scope. + + This function generates the following ASL code: + Scope (\_SB) { + Name (L000, Package() { + 0, // Version + 0, // Level Index + X, // Count + Package() { + [An Lpi state] + }, + Package() { + [Another Lpi state] + }, + } // Name L000 + + Name (L001, Package() { + ... + } // Name L001 + + ... + } // Scope /_SB + + The Lpi states are fetched from the Configuration Manager. + The names of the Lpi states are generated from the TokenTable. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GenerateLpiStates ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + + UINT32 Index; + UINT32 LastIndex; + + AML_OBJECT_NODE_HANDLE LpiNode; + CM_ARM_OBJ_REF * LpiRefInfo; + UINT32 LpiRefInfoCount; + UINT32 LpiRefIndex; + CM_ARM_LPI_INFO * LpiInfo; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + LastIndex = Generator->TokenTable.LastIndex; + + // For each entry in the TokenTable, create a name in the AML namespace + // under SB_SCOPE, to store the Lpi states associated with the LpiToken. + for (Index = 0; Index < LastIndex; Index++) { + Status = WriteAslName ('L', Index, AslName); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // We do not support the LevelId field for now, let it to 0. + Status = AmlCreateLpiNode (AslName, 1, 0, ScopeNode, &LpiNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Fetch the LPI objects referenced by the token. + Status = GetEArmObjCmRef ( + CfgMgrProtocol, + Generator->TokenTable.Table[Index], + &LpiRefInfo, + &LpiRefInfoCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + for (LpiRefIndex = 0; LpiRefIndex < LpiRefInfoCount; LpiRefIndex++) { + // For each CM_ARM_LPI_INFO referenced by the token, add an Lpi state. + Status = GetEArmObjLpiInfo ( + CfgMgrProtocol, + LpiRefInfo[LpiRefIndex].ReferenceToken, + &LpiInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlAddLpiState ( + LpiInfo->MinResidency, + LpiInfo->WorstCaseWakeLatency, + LpiInfo->Flags, + LpiInfo->ArchFlags, + LpiInfo->ResCntFreq, + LpiInfo->EnableParentState, + LpiInfo->IsInteger ? + NULL : + &LpiInfo->RegisterEntryMethod, + LpiInfo->IsInteger ? + LpiInfo->IntegerEntryMethod : + 0, + &LpiInfo->ResidencyCounterRegister, + &LpiInfo->UsageCounterRegister, + LpiInfo->StateName, + LpiNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // for LpiRefIndex + } // for Index + + return EFI_SUCCESS; +} + +/** Create a Cpu in the AML namespace. + + This generates the following ASL code: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] ParentNode Parent node to attach the Cpu node to. + @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. + @param [in] CpuIndex Index used to generate the node name. + @param [out] CpuNodePtr If not NULL, return the created Cpu node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpu ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN AML_NODE_HANDLE ParentNode, + IN CM_ARM_GICC_INFO * GicCInfo, + IN UINT32 CpuIndex, + OUT AML_OBJECT_NODE_HANDLE * CpuNodePtr OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE CpuNode; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (ParentNode != NULL); + ASSERT (GicCInfo != NULL); + + Status = WriteAslName ('C', CpuIndex, AslName); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenDevice (AslName, ParentNode, &CpuNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ( + "_UID", + GicCInfo->AcpiProcessorUid, + CpuNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameString ( + "_HID", + ACPI_HID_PROCESSOR_DEVICE, + CpuNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If requested, return the handle to the CpuNode. + if (CpuNodePtr != NULL) { + *CpuNodePtr = CpuNode; + } + + return Status; +} + +/** Create a Cpu in the AML namespace from a CM_ARM_PROC_HIERARCHY_INFO + CM object. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ParentNode Parent node to attach the Cpu node to. + @param [in] CpuIndex Index used to generate the node name. + @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO describing + the Cpu. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpuFromProcHierarchy ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN AML_NODE_HANDLE ParentNode, + IN UINT32 CpuIndex, + IN CM_ARM_PROC_HIERARCHY_INFO * ProcHierarchyNodeInfo + ) +{ + EFI_STATUS Status; + CM_ARM_GICC_INFO * GicCInfo; + AML_OBJECT_NODE_HANDLE CpuNode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ParentNode != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ProcHierarchyNodeInfo->GicCToken != CM_NULL_TOKEN); + + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + ProcHierarchyNodeInfo->GicCToken, + &GicCInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = CreateAmlCpu (Generator, ParentNode, GicCInfo, CpuIndex, &CpuNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If a set of Lpi states is associated with the + // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them. + if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { + Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} + +/** Create a Cluster in the AML namespace. + + Any CM_ARM_PROC_HIERARCHY_INFO object with the following flags is + assumed to be a cluster: + - EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL + - EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID + - EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF + + This generates the following ASL code: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0010") + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ParentNode Parent node to attach the Cluster + node to. + @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO object used + to create the node. + @param [in] ClusterIndex Index used to generate the node name. + @param [out] ClusterNodePtr If success, contains the created Cluster + node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCluster ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN AML_NODE_HANDLE ParentNode, + IN CM_ARM_PROC_HIERARCHY_INFO * ProcHierarchyNodeInfo, + IN UINT32 ClusterIndex, + OUT AML_OBJECT_NODE_HANDLE * ClusterNodePtr + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE ClusterNode; + CHAR8 AslNameCluster[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ParentNode != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ClusterNodePtr != NULL); + + Status = WriteAslName ('C', ClusterIndex, AslNameCluster); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenDevice (AslNameCluster, ParentNode, &ClusterNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Use the ClusterIndex for the _UID value as there is no AcpiProcessorUid + // and EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID is set for non-Cpus. + Status = AmlCodeGenNameInteger ( + "_UID", + ClusterIndex, + ClusterNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameString ( + "_HID", + ACPI_HID_PROCESSOR_CONTAINER_DEVICE, + ClusterNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If a set of Lpi states are associated with the + // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them. + if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { + Status = CreateAmlLpiMethod ( + Generator, + ProcHierarchyNodeInfo, + ClusterNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + *ClusterNodePtr = ClusterNode; + + return Status; +} + +/** Create an AML representation of the Cpu topology. + + A cluster is by extension any non-leave device in the cpu topology. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] NodeToken Token of the CM_ARM_PROC_HIERARCHY_INFO + currently handled. + Cannot be CM_NULL_TOKEN. + @param [in] ParentNode Parent node to attach the created + node to. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpuTopologyTree ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN CM_OBJECT_TOKEN NodeToken, + IN AML_NODE_HANDLE ParentNode + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 CpuIndex; + UINT32 ClusterIndex; + AML_OBJECT_NODE_HANDLE ClusterNode; + + ASSERT (Generator != NULL); + ASSERT (Generator->ProcNodeList != NULL); + ASSERT (Generator->ProcNodeCount != 0); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (NodeToken != CM_NULL_TOKEN); + ASSERT (ParentNode != NULL); + + CpuIndex = 0; + ClusterIndex = 0; + + for (Index = 0; Index < Generator->ProcNodeCount; Index++) { + // Find the children of the CM_ARM_PROC_HIERARCHY_INFO + // currently being handled (i.e. ParentToken == NodeToken). + if (Generator->ProcNodeList[Index].ParentToken == NodeToken) { + + // Only Cpus (leaf nodes in this tree) have a GicCToken. + // Create a Cpu node. + if (Generator->ProcNodeList[Index].GicCToken != CM_NULL_TOKEN) { + if ((Generator->ProcNodeList[Index].Flags & PPTT_PROCESSOR_MASK) != + PPTT_CPU_PROCESSOR_MASK) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for cpu: 0x%x.\n", + Generator->ProcNodeList[Index].Flags + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = CreateAmlCpuFromProcHierarchy ( + Generator, + CfgMgrProtocol, + ParentNode, + CpuIndex, + &Generator->ProcNodeList[Index] + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + CpuIndex++; + + } else { + // If this is not a Cpu, then this is a cluster. + + // Acpi processor Id for clusters is not handled. + if ((Generator->ProcNodeList[Index].Flags & PPTT_PROCESSOR_MASK) != + PPTT_CLUSTER_PROCESSOR_MASK) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for cluster: 0x%x.\n", + Generator->ProcNodeList[Index].Flags + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = CreateAmlCluster ( + Generator, + CfgMgrProtocol, + ParentNode, + &Generator->ProcNodeList[Index], + ClusterIndex, + &ClusterNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Nodes must have a unique name in the ASL namespace. + // Reset the Cpu index whenever we create a new Cluster. + ClusterIndex++; + CpuIndex = 0; + + // Recursively continue creating an AML tree. + Status = CreateAmlCpuTopologyTree ( + Generator, + CfgMgrProtocol, + Generator->ProcNodeList[Index].Token, + ClusterNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } // if ParentToken == NodeToken + } // for + + return EFI_SUCCESS; +} + +/** Create the processor hierarchy AML tree from CM_ARM_PROC_HIERARCHY_INFO + CM objects. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateTopologyFromProcHierarchy ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 TopLevelProcNodeIndex; + + ASSERT (Generator != NULL); + ASSERT (Generator->ProcNodeCount != 0); + ASSERT (Generator->ProcNodeList != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + TopLevelProcNodeIndex = MAX_UINT32; + + Status = TokenTableInitialize (Generator, Generator->ProcNodeCount); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // It is assumed that there is one unique CM_ARM_PROC_HIERARCHY_INFO + // structure with no ParentToken and the EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL + // flag set. All other CM_ARM_PROC_HIERARCHY_INFO are non-physical and + // have a ParentToken. + for (Index = 0; Index < Generator->ProcNodeCount; Index++) { + if ((Generator->ProcNodeList[Index].ParentToken == CM_NULL_TOKEN) && + (Generator->ProcNodeList[Index].Flags & + EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL)) { + if (TopLevelProcNodeIndex != MAX_UINT32) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Top level CM_ARM_PROC_HIERARCHY_INFO " + "must be unique\n" + )); + ASSERT (0); + goto exit_handler; + } + TopLevelProcNodeIndex = Index; + } + } // for + + Status = CreateAmlCpuTopologyTree ( + Generator, + CfgMgrProtocol, + Generator->ProcNodeList[TopLevelProcNodeIndex].Token, + ScopeNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + Status = GenerateLpiStates (Generator, CfgMgrProtocol, ScopeNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + +exit_handler: + TokenTableFree (Generator); + return Status; +} + +/** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO + CM objects. + + A cluster is by extension any non-leave device in the cpu topology. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateTopologyFromGicC ( + IN ACPI_CPU_TOPOLOGY_GENERATOR * Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + CM_ARM_GICC_INFO * GicCInfo; + UINT32 GicCInfoCount; + UINT32 Index; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GicCInfo, + &GicCInfoCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // For each CM_ARM_GICC_INFO object, create an AML node. + for (Index = 0; Index < GicCInfoCount; Index++) { + Status = CreateAmlCpu ( + Generator, + ScopeNode, + &GicCInfo[Index], + Index, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + break; + } + } // for + + return Status; +} + +/** Construct the SSDT Cpu Topology ACPI table. + + This function invokes the Configuration Manager protocol interface + to get the required hardware information for generating the ACPI + table. + + If this function allocates any resources then they must be freed + in the FreeXXXXTableResources function. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [out] Table Pointer to the constructed ACPI Table. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtCpuTopologyTable ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table + ) +{ + EFI_STATUS Status; + AML_ROOT_NODE_HANDLE RootNode; + AML_OBJECT_NODE_HANDLE ScopeNode; + CM_ARM_PROC_HIERARCHY_INFO * ProcHierarchyNodeList; + UINT32 ProcHierarchyNodeCount; + ACPI_CPU_TOPOLOGY_GENERATOR * Generator; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + Generator = (ACPI_CPU_TOPOLOGY_GENERATOR*)This; + + Status = AddSsdtAcpiHeader ( + CfgMgrProtocol, + This, + AcpiTableInfo, + &RootNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + + // Get the processor hierarchy info and update the processor topology + // structure count with Processor Hierarchy Nodes (Type 0) + Status = GetEArmObjProcHierarchyInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ProcHierarchyNodeList, + &ProcHierarchyNodeCount + ); + if (EFI_ERROR (Status) && + (Status != EFI_NOT_FOUND)) { + goto exit_handler; + } + + if (Status == EFI_NOT_FOUND) { + // If hierarchy information is not found generate a flat topology + // using CM_ARM_GICC_INFO objects. + Status = CreateTopologyFromGicC ( + Generator, + CfgMgrProtocol, + ScopeNode + ); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + } else { + // Generate the topology from CM_ARM_PROC_HIERARCHY_INFO objects. + Generator->ProcNodeList = ProcHierarchyNodeList; + Generator->ProcNodeCount = ProcHierarchyNodeCount; + + Status = CreateTopologyFromProcHierarchy ( + Generator, + CfgMgrProtocol, + ScopeNode + ); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + } + + Status = AmlSerializeDefinitionBlock ( + RootNode, + Table + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Failed to Serialize SSDT Table Data." + " Status = %r\n", + Status + )); + goto exit_handler; + } + +exit_handler: + // Delete the RootNode and its attached children. + return AmlDeleteTree (RootNode); +} + +/** Free any resources allocated for constructing the + SSDT Cpu Topology ACPI table. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in, out] Table Pointer to the ACPI Table. + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +FreeSsdtCpuTopologyTableResources ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table + ) +{ + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CPU-TOPOLOGY: Invalid Table Pointer\n")); + ASSERT ((Table != NULL) && (*Table != NULL)); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** This macro defines the SSDT Cpu Topology Table Generator revision. +*/ +#define SSDT_CPU_TOPOLOGY_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SSDT Cpu Topology Table Generator. +*/ +STATIC +ACPI_CPU_TOPOLOGY_GENERATOR SsdtCpuTopologyGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology), + // Generator Description + L"ACPI.STD.SSDT.CPU.TOPOLOGY.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision - Unused + 0, + // Minimum ACPI Table Revision - Unused + 0, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SSDT_CPU_TOPOLOGY_GENERATOR_REVISION, + // Build Table function + BuildSsdtCpuTopologyTable, + // Free Resource function + FreeSsdtCpuTopologyTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL + }, + + // Private fields are defined from here. + + // TokenTable + { + // Table + NULL, + // LastIndex + 0 + }, + // ProcNodeList + NULL, + // ProcNodeCount + 0 +}; + +/** Register the Generator with the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The Generator for the Table ID + is already registered. +**/ +EFI_STATUS +EFIAPI +AcpiSsdtCpuTopologyLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * SystemTable + ) +{ + EFI_STATUS Status; + Status = RegisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-CPU-TOPOLOGY: Register Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSsdtCpuTopologyLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * SystemTable + ) +{ + EFI_STATUS Status; + Status = DeregisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-CPU-TOPOLOGY: Deregister Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h new file mode 100644 index 000000000000..f6e8a754af7d --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h @@ -0,0 +1,134 @@ +/** @file + SSDT Cpu Topology Table Generator. + + Copyright (c) 2021, Arm Limited. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors +**/ + +#ifndef SSDT_CPU_TOPOLOGY_GENERATOR_H_ +#define SSDT_CPU_TOPOLOGY_GENERATOR_H_ + +#pragma pack(1) + +// Mask for the flags that need to be checked. +#define PPTT_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) + +// Mask for the cpu flags. +#define PPTT_CPU_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) + +// Mask for the cluster flags. +// Even though a _UID is generated for clusters, it is simpler to use +// EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID and to not match the cluster id of +// the PPTT table (not sure the PPTT table is generated). +#define PPTT_CLUSTER_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF << 3)) + +/** LPI states are stored in the ASL namespace at '\_SB_.Lxxx', + with xxx being the node index of the LPI state. +*/ +#define SB_SCOPE "\\_SB_" +#define SB_SCOPE_PREFIX SB_SCOPE "." +/// Size of the SB_SCOPE_PREFIX string. +#define SB_SCOPE_PREFIX_SIZE sizeof (SB_SCOPE_PREFIX) + +/// HID for a processor device. +#define ACPI_HID_PROCESSOR_DEVICE "ACPI0007" + +/// HID for a processor container device. +#define ACPI_HID_PROCESSOR_CONTAINER_DEVICE "ACPI0010" + +/** Node names of Cpus and Clusters are 'Cxxx', and 'Lxxx' for LPI states. + The 'xxx' is an index on 12 bits is given to node name, + thus the limitation in the number of nodes. +*/ +#define MAX_NODE_COUNT (1 << 12) + +/** A structure used to handle the Lpi structures referencing. + + A CM_ARM_PROC_HIERARCHY_INFO structure references a CM_ARM_OBJ_REF. + This CM_ARM_OBJ_REF references CM_ARM_LPI_INFO structures. + + Example: + (Cpu0) (Cpu1) + CM_ARM_PROC_HIERARCHY_INFO CM_ARM_PROC_HIERARCHY_INFO + | | + +---------------------------------------- + | + v + (List of references to Lpi states) + CM_ARM_OBJ_REF + | + +---------------------------------------- + | | + v v + (A first Lpi state) (A second Lpi state) + CM_ARM_LPI_INFO[0] CM_ARM_LPI_INFO[1] + + Here, Cpu0 and Cpu1 have the same Lpi states. Both CM_ARM_PROC_HIERARCHY_INFO + structures reference the same CM_ARM_OBJ_REF. An entry is created in the + TokenTable such as: + 0 <-> CM_ARM_OBJ_REF + + This will lead to the creation of this pseudo-ASL code where Cpu0 and Cpu1 + return the same object at \_SB.L000: + Scope (\_SB) { + Device (C000) { + [...] + Method (_LPI) { + Return (\_SB.L000) + } + } // C000 + + Device (C001) { + [...] + Method (_LPI) { + Return (\_SB.L000) + } + } // C001 + + // Lpi states + Name (L000, Package (0x05) { + [...] + } + } +*/ +typedef struct TokenTable { + /// TokenTable, a table allowing to map: + /// Index <-> CM_OBJECT_TOKEN (to CM_ARM_LPI_INFO structures). + CM_OBJECT_TOKEN * Table; + + /// Last used index of the TokenTable. + /// LastIndex is bound by ProcNodeCount. + UINT32 LastIndex; +} TOKEN_TABLE; + +/** A structure holding the Cpu topology generator and additional private data. +*/ +typedef struct AcpiCpuTopologyGenerator { + /// ACPI Table generator header + ACPI_TABLE_GENERATOR Header; + + // Private fields are defined from here. + + /// Private object used to handle token referencing. + TOKEN_TABLE TokenTable; + /// List of CM_ARM_PROC_HIERARCHY_INFO CM objects. + CM_ARM_PROC_HIERARCHY_INFO * ProcNodeList; + /// Count of CM_ARM_PROC_HIERARCHY_INFO CM objects. + UINT32 ProcNodeCount; +} ACPI_CPU_TOPOLOGY_GENERATOR; + +#pragma pack() + +#endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf new file mode 100644 index 000000000000..3e2d15474980 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf @@ -0,0 +1,33 @@ +## @file +# Ssdt Cpu Topology Table Generator +# +# Copyright (c) 2021, Arm Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtCpuTopologyLibArm + FILE_GUID = F2835EB6-4B05-48D4-A475-147DA0F3755C + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSsdtCpuTopologyLibConstructor + DESTRUCTOR = AcpiSsdtCpuTopologyLibDestructor + +[Sources] + SsdtCpuTopologyGenerator.c + SsdtCpuTopologyGenerator.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib -- 2.17.1 |
|
[PATCH v3 20/21] DynamicTablesPkg: Add CM_ARM_LPI_INFO object
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
Introduce the CM_ARM_LPI_INFO CmObj in the ArmNameSpaceObjects. This allows to describe LPI state information, as described in ACPI 6.4, s8.4.4.3 "_LPI (Low Power Idle States)". Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- .../Include/ArmNameSpaceObjects.h | 68 +++++++++++++++++++ .../ConfigurationManagerObjectParser.c | 35 ++++++++++ 2 files changed, 103 insertions(+) diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h index 2244eafaf009..f19c9c706669 100644 --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h @@ -58,6 +58,7 @@ typedef enum ArmObjectID { EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info EArmObjCmn600Info, ///< 36 - CMN-600 Info + EArmObjLpiInfo, ///< 37 - Lpi Info EArmObjMax } EARM_OBJECT_ID; @@ -711,6 +712,10 @@ typedef struct CmArmProcHierarchyInfo { /// the NoOfPrivateResources is 0, in which case it is recommended to set /// this field to CM_NULL_TOKEN. CM_OBJECT_TOKEN PrivateResourcesArrayToken; + /// Optional field: Reference Token for the Lpi state of this processor. + /// Token identifying a CM_ARM_OBJ_REF structure, itself referencing + /// CM_ARM_LPI_INFO objects. + CM_OBJECT_TOKEN LpiToken; } CM_ARM_PROC_HIERARCHY_INFO; /** A structure that describes the Cache Type Structure (Type 1) in PPTT @@ -878,6 +883,69 @@ typedef struct CmArmCmn600Info { CM_ARM_EXTENDED_INTERRUPT DtcInterrupt[4]; } CM_ARM_CMN_600_INFO; +/** A structure that describes the Lpi information. + + The Low Power Idle states are described in DSDT/SSDT and associated + to cpus/clusters in the cpu topology. + + ID: EArmObjLpiInfo +*/ +typedef struct CmArmLpiInfo { + /** Minimum Residency. Time in microseconds after which a + state becomes more energy efficient than any shallower state. + */ + UINT32 MinResidency; + + /** Worst case time in microseconds from a wake interrupt + being asserted to the return to a running state + */ + UINT32 WorstCaseWakeLatency; + + /** Flags. + */ + UINT32 Flags; + + /** Architecture specific context loss flags. + */ + UINT32 ArchFlags; + + /** Residency counter frequency in cycles-per-second (Hz). + */ + UINT32 ResCntFreq; + + /** Every shallower power state in the parent is also enabled. + */ + UINT32 EnableParentState; + + /** The EntryMethod _LPI field can be described as an integer + or in a Register resource data descriptor. + + If IsInteger is TRUE, the IntegerEntryMethod field is used. + If IsInteger is FALSE, the RegisterEntryMethod field is used. + */ + BOOLEAN IsInteger; + + /** EntryMethod described as an Integer. + */ + UINT64 IntegerEntryMethod; + + /** EntryMethod described as a EFI_ACPI_GENERIC_REGISTER_DESCRIPTOR. + */ + EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE RegisterEntryMethod; + + /** Residency counter register. + */ + EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE ResidencyCounterRegister; + + /** Usage counter register. + */ + EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE UsageCounterRegister; + + /** String representing the Lpi state + */ + CHAR8 StateName[16]; +} CM_ARM_LPI_INFO; + #pragma pack() #endif // ARM_NAMESPACE_OBJECTS_H_ diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c index ee2918ab5cc6..2337d47e3fb3 100644 --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c @@ -368,6 +368,39 @@ STATIC CONST CM_OBJ_PARSER CmArmCmn600InfoParser[] = { {"DtcFlags[3]", 4, "0x%x", NULL} }; +/** A parser for the EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE structure. +*/ +STATIC CONST CM_OBJ_PARSER AcpiGenericAddressParser[] = { + {"AddressSpaceId", 1, "%d", NULL}, + {"RegisterBitWidth", 1, "%d", NULL}, + {"RegisterBitOffset", 1, "%d", NULL}, + {"AccessSize", 1, "%d", NULL}, + {"Address", 8, "0x%llx", NULL}, +}; + +/** A parser for EArmObjLpiInfo. +*/ +STATIC CONST CM_OBJ_PARSER CmArmLpiInfoParser[] = { + {"MinResidency", 4, "0x%llx", NULL}, + {"WorstCaseWakeLatency", 4, "0x%llx", NULL}, + {"Flags", 4, "0x%llx", NULL}, + {"ArchFlags", 4, "0x%llx", NULL}, + {"ResCntFreq", 4, "0x%llx", NULL}, + {"EnableParentState", 4, "0x%llx", NULL}, + {"IsInteger", 1, "%d", NULL}, + {"IntegerEntryMethod", 8, "0x%llx", NULL}, + {"RegisterEntryMethod", sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE), + NULL, NULL, AcpiGenericAddressParser, + ARRAY_SIZE (AcpiGenericAddressParser)}, + {"ResidencyCounterRegister", sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE), + NULL, NULL, AcpiGenericAddressParser, + ARRAY_SIZE (AcpiGenericAddressParser)}, + {"UsageCounterRegister", sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE), + NULL, NULL, AcpiGenericAddressParser, + ARRAY_SIZE (AcpiGenericAddressParser)}, + {"StateName", 16, "0x%a", NULL}, +}; + /** A parser for Arm namespace objects. */ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = { @@ -440,6 +473,8 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = { ARRAY_SIZE (CmArmSerialPortInfoParser)}, {"EArmObjCmn600Info", CmArmCmn600InfoParser, ARRAY_SIZE (CmArmCmn600InfoParser)}, + {"EArmObjLpiInfo", CmArmLpiInfoParser, + ARRAY_SIZE (CmArmLpiInfoParser)}, {"EArmObjMax", NULL, 0}, }; -- 2.17.1 |
|
[PATCH v3 19/21] DynamicTablesPkg: AML code generation to add an _LPI state
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
Add AmlAddLpiState() to generates AML code to add an _LPI state to an _LPI object created using AmlCreateLpiNode(). AmlAddLpiState increments the count of LPI states in the LPI node by one, and adds the following package: Package() { MinResidency, WorstCaseWakeLatency, Flags, ArchFlags, ResCntFreq, EnableParentState, (GenericRegisterDescriptor != NULL) ? // Entry method. If a ResourceTemplate(GenericRegisterDescriptor) : // Register is given, Integer, // use it. Use the // Integer otherwise ResourceTemplate() { // NULL Residency Register (SystemMemory, 0, 0, 0, 0) // Counter }, ResourceTemplate() { // NULL Usage Counter Register (SystemMemory, 0, 0, 0, 0) }, "" // NULL State Name }, Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- .../Include/Library/AmlLib/AmlLib.h | 71 +++ .../Common/AmlLib/CodeGen/AmlCodeGen.c | 459 ++++++++++++++++++ 2 files changed, 530 insertions(+) diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h index 40c45073d303..4932f6fd9c8b 100644 --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -716,6 +716,77 @@ AmlCreateLpiNode ( OUT AML_OBJECT_NODE_HANDLE * NewLpiNode OPTIONAL ); +/** Add an _LPI state to a LPI node created using AmlCreateLpiNode (). + + AmlAddLpiState () increments the Count of LPI states in the LPI node by one, + and adds the following package: + Package() { + MinResidency, + WorstCaseWakeLatency, + Flags, + ArchFlags, + ResCntFreq, + EnableParentState, + (GenericRegisterDescriptor != NULL) ? // Entry method. If a + ResourceTemplate(GenericRegisterDescriptor) : // Register is given, + Integer, // use it. Use the + // Integer otherwise. + ResourceTemplate() { // NULL Residency Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + ResourceTemplate() { // NULL Usage Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + "" // NULL State Name + }, + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @ingroup CodeGenApis + + @param [in] MinResidency Minimum Residency. + @param [in] WorstCaseWakeLatency Worst case wake-up latency. + @param [in] Flags Flags. + @param [in] ArchFlags Architectural flags. + @param [in] ResCntFreq Residency Counter Frequency. + @param [in] EnableParentState Enabled Parent State. + @param [in] GenericRegisterDescriptor Entry Method. + If not NULL, use this Register to + describe the entry method address. + @param [in] Integer Entry Method. + If GenericRegisterDescriptor is NULL, + take this value. + @param [in] ResidencyCounterRegister If not NULL, use it to populate the + residency counter register. + @param [in] UsageCounterRegister If not NULL, use it to populate the + usage counter register. + @param [in] StateName If not NULL, use it to populate the + state name. + @param [in] LpiNode Lpi node created with the function + AmlCreateLpiNode to which the new LPI + state is appended. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddLpiState ( + IN UINT32 MinResidency, + IN UINT32 WorstCaseWakeLatency, + IN UINT32 Flags, + IN UINT32 ArchFlags, + IN UINT32 ResCntFreq, + IN UINT32 EnableParentState, + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * GenericRegisterDescriptor, OPTIONAL + IN UINT64 Integer, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * ResidencyCounterRegister, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * UsageCounterRegister, OPTIONAL + IN CHAR8 * StateName, OPTIONAL + IN AML_OBJECT_NODE_HANDLE LpiNode + ); + // DEPRECATED APIS #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index 9af7a725d5c1..64064018aecb 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -12,6 +12,7 @@ #include <AmlCoreInterface.h> #include <AmlEncoding/Aml.h> +#include <Api/AmlApiHelper.h> #include <CodeGen/AmlResourceDataCodeGen.h> #include <Tree/AmlNode.h> #include <Tree/AmlTree.h> @@ -1574,3 +1575,461 @@ error_handler: } return Status; } + +/** Add an _LPI state to a LPI node created using AmlCreateLpiNode. + + AmlAddLpiState increments the Count of LPI states in the LPI node by one, + and adds the following package: + Package() { + MinResidency, + WorstCaseWakeLatency, + Flags, + ArchFlags, + ResCntFreq, + EnableParentState, + (GenericRegisterDescriptor != NULL) ? // Entry method. If a + ResourceTemplate(GenericRegisterDescriptor) : // Register is given, + Integer, // use it. Use the + // Integer otherwise. + ResourceTemplate() { // NULL Residency Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + ResourceTemplate() { // NULL Usage Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + "" // NULL State Name + }, + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @param [in] MinResidency Minimum Residency. + @param [in] WorstCaseWakeLatency Worst case wake-up latency. + @param [in] Flags Flags. + @param [in] ArchFlags Architectural flags. + @param [in] ResCntFreq Residency Counter Frequency. + @param [in] EnableParentState Enabled Parent State. + @param [in] GenericRegisterDescriptor Entry Method. + If not NULL, use this Register to + describe the entry method address. + @param [in] Integer Entry Method. + If GenericRegisterDescriptor is NULL, + take this value. + @param [in] ResidencyCounterRegister If not NULL, use it to populate the + residency counter register. + @param [in] UsageCounterRegister If not NULL, use it to populate the + usage counter register. + @param [in] StateName If not NULL, use it to populate the + state name. + @param [in] LpiNode Lpi node created with the function + AmlCreateLpiNode to which the new LPI + state is appended. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddLpiState ( + IN UINT32 MinResidency, + IN UINT32 WorstCaseWakeLatency, + IN UINT32 Flags, + IN UINT32 ArchFlags, + IN UINT32 ResCntFreq, + IN UINT32 EnableParentState, + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * GenericRegisterDescriptor, OPTIONAL + IN UINT64 Integer, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * ResidencyCounterRegister, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * UsageCounterRegister, OPTIONAL + IN CHAR8 * StateName, OPTIONAL + IN AML_OBJECT_NODE_HANDLE LpiNode + ) +{ + EFI_STATUS Status; + AML_DATA_NODE_HANDLE RdNode; + AML_OBJECT_NODE_HANDLE PackageNode; + AML_OBJECT_NODE_HANDLE IntegerNode; + AML_OBJECT_NODE_HANDLE StringNode; + AML_OBJECT_NODE_HANDLE NewLpiPackageNode; + AML_OBJECT_NODE_HANDLE ResourceTemplateNode; + + UINT32 Index; + AML_OBJECT_NODE_HANDLE CountNode; + UINT64 Count; + + if ((LpiNode == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)LpiNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (LpiNode, AML_NAME_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + RdNode = 0; + StringNode = NULL; + IntegerNode = NULL; + ResourceTemplateNode = NULL; + + // AmlCreateLpiNode () created a LPI container such as: + // Name (_LPI, Package ( + // 0, // Revision + // 1, // LevelId + // 0 // Count + // )) + // Get the LPI container, a PackageOp object node stored as the 2nd fixed + // argument (i.e. index 1) of LpiNode. + PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + LpiNode, + EAmlParseIndexTerm1 + ); + if ((PackageNode == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CountNode = NULL; + // The third variable argument is the LPI Count node. + for (Index = 0; Index < 3; Index++) { + CountNode = (AML_OBJECT_NODE_HANDLE)AmlGetNextVariableArgument ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)CountNode + ); + if (CountNode == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + Status = AmlNodeGetIntegerValue (CountNode, &Count); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + Status = AmlUpdateInteger (CountNode, Count + 1); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenPackage (&NewLpiPackageNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // MinResidency + Status = AmlCodeGenInteger (MinResidency, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // WorstCaseWakeLatency + Status = AmlCodeGenInteger (WorstCaseWakeLatency, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // Flags + Status = AmlCodeGenInteger (Flags, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // ArchFlags + Status = AmlCodeGenInteger (ArchFlags, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // ResCntFreq + Status = AmlCodeGenInteger (ResCntFreq, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // EnableParentState + Status = AmlCodeGenInteger (EnableParentState, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // Entry Method + if (GenericRegisterDescriptor != NULL) { + // Entry Method: As a Register resource data + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + ResourceTemplateNode = NULL; + goto error_handler; + } + Status = AmlCodeGenRdRegister ( + GenericRegisterDescriptor->AddressSpaceId, + GenericRegisterDescriptor->RegisterBitWidth, + GenericRegisterDescriptor->RegisterBitOffset, + GenericRegisterDescriptor->Address, + GenericRegisterDescriptor->AccessSize, + NULL, + &RdNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + RdNode = NULL; + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + } else { + // Entry Method: As an integer + Status = AmlCodeGenInteger (Integer, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + } + + // Residency Counter Register. + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + ResourceTemplateNode = NULL; + goto error_handler; + } + if (ResidencyCounterRegister != NULL) { + Status = AmlCodeGenRdRegister ( + ResidencyCounterRegister->AddressSpaceId, + ResidencyCounterRegister->RegisterBitWidth, + ResidencyCounterRegister->RegisterBitOffset, + ResidencyCounterRegister->Address, + ResidencyCounterRegister->AccessSize, + NULL, + &RdNode + ); + } else { + Status = AmlCodeGenRdRegister ( + EFI_ACPI_6_4_SYSTEM_MEMORY, + 0, + 0, + 0, + 0, + NULL, + &RdNode + ); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + RdNode = NULL; + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + + // Usage Counter Register. + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + ResourceTemplateNode = NULL; + goto error_handler; + } + if (UsageCounterRegister != NULL) { + Status = AmlCodeGenRdRegister ( + UsageCounterRegister->AddressSpaceId, + UsageCounterRegister->RegisterBitWidth, + UsageCounterRegister->RegisterBitOffset, + UsageCounterRegister->Address, + UsageCounterRegister->AccessSize, + NULL, + &RdNode + ); + } else { + Status = AmlCodeGenRdRegister ( + EFI_ACPI_6_4_SYSTEM_MEMORY, + 0, + 0, + 0, + 0, + NULL, + &RdNode + ); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + RdNode = NULL; + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + + // State name. + if (UsageCounterRegister != NULL) { + Status = AmlCodeGenString (StateName, &StringNode); + } else { + Status = AmlCodeGenString ("", &StringNode); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + StringNode = NULL; + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)StringNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + StringNode = NULL; + + // Add the new LPI state to the LpiNode. + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)NewLpiPackageNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + if (RdNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)RdNode); + } + if (NewLpiPackageNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)NewLpiPackageNode); + } + if (StringNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)StringNode); + } + if (IntegerNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode); + } + if (ResourceTemplateNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode); + } + + return Status; +} -- 2.17.1 |
|
[PATCH v3 18/21] DynamicTablesPkg: AML code generation for a _LPI object
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
_LPI object provides a method to describe Low Power Idle states that define the local power states for each node in a hierarchical processor topology. Therefore, add AmlCreateLpiNode() to generate code for a _LPI object. AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is equivalent of the following ASL code: Name (_LPI, Package ( 0, // Revision 1, // LevelId 0 // Count )) Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- .../Include/Library/AmlLib/AmlLib.h | 44 ++++++ .../Common/AmlLib/CodeGen/AmlCodeGen.c | 133 ++++++++++++++++++ 2 files changed, 177 insertions(+) diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h index 7740aac24470..40c45073d303 100644 --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -672,6 +672,50 @@ AmlCodeGenMethodRetNameString ( OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL ); +/** Create a _LPI name. + + AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is + equivalent of the following ASL code: + Name (_LPI, Package ( + 0, // Revision + 1, // LevelId + 0 // Count + )) + + This function doesn't define any LPI state. As shown above, the count + of _LPI state is set to 0. + The AmlAddLpiState () function must be used to add LPI states. + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @ingroup CodeGenApis + + @param [in] LpiNameString The new LPI 's object name. + Must be a NULL-terminated ASL NameString + e.g.: "_LPI", "DEV0.PLPI", etc. + The input string is copied. + @param [in] Revision Revision number of the _LPI states. + @param [in] LevelId A platform defined number that identifies the + level of hierarchy of the processor node to + which the LPI states apply. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewLpiNode If success, contains the created node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateLpiNode ( + IN CONST CHAR8 * LpiNameString, + IN UINT16 Revision, + IN UINT64 LevelId, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewLpiNode OPTIONAL + ); + // DEPRECATED APIS #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index f59a9599930f..9af7a725d5c1 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -1441,3 +1441,136 @@ error_handler: } return Status; } + +/** Create a _LPI name. + + AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is + equivalent of the following ASL code: + Name (_LPI, Package ( + 0, // Revision + 1, // LevelId + 0 // Count + )) + + This function doesn't define any LPI state. As shown above, the count + of _LPI state is set to 0. + The AmlAddLpiState () function allows to add LPI states. + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @param [in] LpiNameString The new LPI 's object name. + Must be a NULL-terminated ASL NameString + e.g.: "_LPI", "DEV0.PLPI", etc. + The input string is copied. + @param [in] Revision Revision number of the _LPI states. + @param [in] LevelId A platform defined number that identifies the + level of hierarchy of the processor node to + which the LPI states apply. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewLpiNode If success, contains the created node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateLpiNode ( + IN CONST CHAR8 * LpiNameString, + IN UINT16 Revision, + IN UINT64 LevelId, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewLpiNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE PackageNode; + AML_OBJECT_NODE_HANDLE IntegerNode; + + if ((LpiNameString == NULL) || + ((ParentNode == NULL) && (NewLpiNode == NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + IntegerNode = NULL; + + Status = AmlCodeGenPackage (&PackageNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Create and attach Revision + Status = AmlCodeGenInteger (Revision, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + IntegerNode = NULL; + + // Create and attach LevelId + Status = AmlCodeGenInteger (LevelId, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + IntegerNode = NULL; + + // Create and attach Count. No LPI state is added, so 0. + Status = AmlCodeGenInteger (0, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + IntegerNode = NULL; + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + IntegerNode = NULL; + + Status = AmlCodeGenName (LpiNameString, PackageNode, ParentNode, NewLpiNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + AmlDeleteTree ((AML_NODE_HANDLE)PackageNode); + if (IntegerNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode); + } + return Status; +} -- 2.17.1 |
|
[PATCH v3 17/21] DynamicTablesPkg: AML code generation for a Method returning a NS
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
Add AmlCodeGenMethodRetNameString() to generate AML code to create a Method returning a NameString (NS). AmlCodeGenMethodRetNameString ( "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode ); is equivalent of the following ASL code: Method(MET0, 1, Serialized, 3) { Return (_CRS) } Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- .../Include/Library/AmlLib/AmlLib.h | 53 +++++++++ .../Common/AmlLib/CodeGen/AmlCodeGen.c | 106 ++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h index 6824cf3a6c82..7740aac24470 100644 --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -619,6 +619,59 @@ AmlCodeGenScope ( OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL ); +/** AML code generation for a method returning a NameString. + + AmlCodeGenMethodRetNameString ( + "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode + ); + is equivalent of the following ASL code: + Method(MET0, 1, Serialized, 3) { + Return (_CRS) + } + + The ASL parameters "ReturnType" and "ParameterTypes" are not asked + in this function. They are optional parameters in ASL. + + @ingroup CodeGenApis + + @param [in] MethodNameString The new Method's name. + Must be a NULL-terminated ASL NameString + e.g.: "MET0", "_SB.MET0", etc. + The input string is copied. + @param [in] ReturnedNameString The name of the object returned by the + method. Optional parameter, can be: + - NULL (ignored). + - A NULL-terminated ASL NameString. + e.g.: "MET0", "_SB.MET0", etc. + The input string is copied. + @param [in] NumArgs Number of arguments. + Must be 0 <= NumArgs <= 6. + @param [in] IsSerialized TRUE is equivalent to Serialized. + FALSE is equivalent to NotSerialized. + Default is NotSerialized in ASL spec. + @param [in] SyncLevel Synchronization level for the method. + Must be 0 <= SyncLevel <= 15. + Default is 0 in ASL. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewObjectNode If success, contains the created node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenMethodRetNameString ( + IN CONST CHAR8 * MethodNameString, + IN CONST CHAR8 * ReturnedNameString, OPTIONAL + IN UINT8 NumArgs, + IN BOOLEAN IsSerialized, + IN UINT8 SyncLevel, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ); + // DEPRECATED APIS #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index 93d4ba79e937..f59a9599930f 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -1335,3 +1335,109 @@ exit_handler: } return Status; } + +/** AML code generation for a method returning a NameString. + + AmlCodeGenMethodRetNameString ( + "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode + ); + is equivalent of the following ASL code: + Method(MET0, 1, Serialized, 3) { + Return (_CRS) + } + + The ASL parameters "ReturnType" and "ParameterTypes" are not asked + in this function. They are optional parameters in ASL. + + @param [in] MethodNameString The new Method's name. + Must be a NULL-terminated ASL NameString + e.g.: "MET0", "_SB.MET0", etc. + The input string is copied. + @param [in] ReturnedNameString The name of the object returned by the + method. Optional parameter, can be: + - NULL (ignored). + - A NULL-terminated ASL NameString. + e.g.: "MET0", "_SB.MET0", etc. + The input string is copied. + @param [in] NumArgs Number of arguments. + Must be 0 <= NumArgs <= 6. + @param [in] IsSerialized TRUE is equivalent to Serialized. + FALSE is equivalent to NotSerialized. + Default is NotSerialized in ASL spec. + @param [in] SyncLevel Synchronization level for the method. + Must be 0 <= SyncLevel <= 15. + Default is 0 in ASL. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewObjectNode If success, contains the created node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenMethodRetNameString ( + IN CONST CHAR8 * MethodNameString, + IN CONST CHAR8 * ReturnedNameString, OPTIONAL + IN UINT8 NumArgs, + IN BOOLEAN IsSerialized, + IN UINT8 SyncLevel, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE MethodNode; + + if ((MethodNameString == NULL) || + ((ParentNode == NULL) && (NewObjectNode == NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Create a Method named MethodNameString. + Status = AmlCodeGenMethod ( + MethodNameString, + NumArgs, + IsSerialized, + SyncLevel, + NULL, + &MethodNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Return ReturnedNameString if provided. + if (ReturnedNameString != NULL) { + Status = AmlCodeGenReturnNameString ( + ReturnedNameString, + (AML_NODE_HANDLE)MethodNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + } + + Status = LinkNode ( + MethodNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + if (MethodNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)MethodNode); + } + return Status; +} -- 2.17.1 |
|
[PATCH v3 16/21] DynamicTablesPkg: AML code generation to Return a NameString
PierreGondois
From: Pierre Gondois <Pierre.Gondois@...>
Add AmlCodeGenReturnNameString() to generate AML code for a Return object node, returning the object as a NameString. AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is equivalent of the following ASL code: Return(NAM1) Reviewed-by: Sami Mujawar <sami.mujawar@...> Signed-off-by: Pierre Gondois <Pierre.Gondois@...> --- .../Common/AmlLib/CodeGen/AmlCodeGen.c | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index dd519bc67007..93d4ba79e937 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -1154,3 +1154,184 @@ error_handler1: } return Status; } + +/** AML code generation for a Return object node. + + AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Return([Content of the ReturnNode]) + + The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states: + DefReturn := ReturnOp ArgObject + ReturnOp := 0xA4 + ArgObject := TermArg => DataRefObject + + Thus, the ReturnNode must be evaluated as a DataRefObject. It can + be a NameString referencing an object. As this CodeGen Api doesn't + do semantic checking, it is strongly advised to check the AML bytecode + generated by this function against an ASL compiler. + + The ReturnNode must be generated inside a Method body scope. + + @param [in] ReturnNode The object returned by the Return ASL statement. + This node is deleted if an error occurs. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + Must be a MethodOp node. + @param [out] NewObjectNode If success, contains the created node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCodeGenReturn ( + IN AML_NODE_HEADER * ReturnNode, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + + if ((ReturnNode == NULL) || + ((ParentNode == NULL) && (NewObjectNode == NULL)) || + ((ParentNode != NULL) && + !AmlNodeCompareOpCode ( + (AML_OBJECT_NODE*)ParentNode, AML_METHOD_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_RETURN_OP, 0), + 0, + &ObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + Status = AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)ReturnNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + ReturnNode = NULL; + + Status = LinkNode ( + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + if (ReturnNode != NULL) { + AmlDeleteTree (ReturnNode); + } + if (ObjectNode != NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + return Status; +} + +/** AML code generation for a Return object node, + returning the object as an input NameString. + + AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Return(NAM1) + + The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states: + DefReturn := ReturnOp ArgObject + ReturnOp := 0xA4 + ArgObject := TermArg => DataRefObject + + Thus, the ReturnNode must be evaluated as a DataRefObject. It can + be a NameString referencing an object. As this CodeGen Api doesn't + do semantic checking, it is strongly advised to check the AML bytecode + generated by this function against an ASL compiler. + + The ReturnNode must be generated inside a Method body scope. + + @param [in] NameString The object referenced by this NameString + is returned by the Return ASL statement. + Must be a NULL-terminated ASL NameString + e.g.: "NAM1", "_SB.NAM1", etc. + The input string is copied. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + Must be a MethodOp node. + @param [out] NewObjectNode If success, contains the created node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCodeGenReturnNameString ( + IN CONST CHAR8 * NameString, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_DATA_NODE * DataNode; + CHAR8 * AmlNameString; + UINT32 AmlNameStringSize; + + DataNode = NULL; + + Status = ConvertAslNameToAmlName (NameString, &AmlNameString); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + Status = AmlCreateDataNode ( + EAmlNodeDataTypeNameString, + (UINT8*)AmlNameString, + AmlNameStringSize, + &DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // AmlCodeGenReturn() deletes DataNode if error. + Status = AmlCodeGenReturn ( + (AML_NODE_HEADER*)DataNode, + ParentNode, + NewObjectNode + ); + ASSERT_EFI_ERROR (Status); + +exit_handler: + if (AmlNameString != NULL) { + FreePool (AmlNameString); + } + return Status; +} -- 2.17.1 |
|