From b0e1cf64e8b8a00fd7cf2034e8ddaeb57dc1945d Mon Sep 17 00:00:00 2001 From: Levi Yun Date: Mon, 11 Nov 2024 12:35:33 +0000 Subject: [PATCH] StandaloneMmPkg: move core entry point lib and cpu driver to ArmPkg StandaloneMmCpu driver is only used for Arm architecture and StandaloneMmCoreEntryPointLib for Arm has specific implementation with StandaloneMmCpu driver. Move StandaloneMmCpu Driver and StandaloneMmCoreEntryPointLib for Arm to ArmPkg. Continuous-integration-options: PatchCheck.ignore-multi-package Signed-off-by: Levi Yun --- ArmPkg/ArmPkg.ci.yaml | 3 +- ArmPkg/ArmPkg.dec | 6 ++ ArmPkg/ArmPkg.dsc | 15 ++++ .../Drivers/StandaloneMmCpu/EventHandle.c | 0 .../Drivers/StandaloneMmCpu/StandaloneMmCpu.c | 0 .../StandaloneMmCpu}/StandaloneMmCpu.h | 0 .../StandaloneMmCpu/StandaloneMmCpu.inf | 4 +- .../Library/ArmStandaloneMmCoreEntryPoint.h | 0 .../Include/Protocol/PiMmCpuDriverEp.h | 0 .../AArch64/ModuleEntryPoint.S | 0 .../Arm/ModuleEntryPoint.S | 0 .../ArmStandaloneMmCoreEntryPoint.c | 3 +- .../ArmStandaloneMmCoreEntryPoint.inf | 72 +++++++++++++++++++ .../SetPermissions.c | 2 +- .../StandaloneMmCoreEntryPoint.inf | 29 -------- StandaloneMmPkg/StandaloneMmPkg.dec | 8 --- StandaloneMmPkg/StandaloneMmPkg.dsc | 9 ++- 17 files changed, 106 insertions(+), 45 deletions(-) rename {StandaloneMmPkg => ArmPkg}/Drivers/StandaloneMmCpu/EventHandle.c (100%) rename {StandaloneMmPkg => ArmPkg}/Drivers/StandaloneMmCpu/StandaloneMmCpu.c (100%) rename {StandaloneMmPkg/Include => ArmPkg/Drivers/StandaloneMmCpu}/StandaloneMmCpu.h (100%) rename {StandaloneMmPkg => ArmPkg}/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf (93%) rename StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h => ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h (100%) rename {StandaloneMmPkg => ArmPkg}/Include/Protocol/PiMmCpuDriverEp.h (100%) rename StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint64.S => ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/AArch64/ModuleEntryPoint.S (100%) rename StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint32.S => ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint.S (100%) rename StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c => ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c (96%) create mode 100644 ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf rename {StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm => ArmPkg/Library/ArmStandaloneMmCoreEntryPoint}/SetPermissions.c (96%) diff --git a/ArmPkg/ArmPkg.ci.yaml b/ArmPkg/ArmPkg.ci.yaml index 292a25c9eb4d..65685b4ea7be 100644 --- a/ArmPkg/ArmPkg.ci.yaml +++ b/ArmPkg/ArmPkg.ci.yaml @@ -51,7 +51,8 @@ "EmbeddedPkg/EmbeddedPkg.dec", "MdeModulePkg/MdeModulePkg.dec", "MdePkg/MdePkg.dec", - "ShellPkg/ShellPkg.dec" + "ShellPkg/ShellPkg.dec", + "StandaloneMmPkg/StandaloneMmPkg.dec" ], # For host based unit tests "AcceptableDependencies-HOST_APPLICATION":[ diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec index df56e6326d08..c65660658d1e 100644 --- a/ArmPkg/ArmPkg.dec +++ b/ArmPkg/ArmPkg.dec @@ -101,6 +101,10 @@ # ArmFfaLib|Include/Library/ArmFfaLib.h + ## @libraryclass Defines a set of interfaces for the MM core entrypoint for + ## AArch64 and ARM. + StandaloneMmCoreEntryPoint|Include/Library/ArmStandaloneMmCoreEntryPoint.h + [Guids.common] gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } } @@ -126,6 +130,8 @@ ## ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h gArmScmiPerformanceProtocolGuid = { 0x9b8ba84, 0x3dd3, 0x49a6, { 0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad } } + gEdkiiPiMmCpuDriverEpProtocolGuid = { 0x6ecbd5a1, 0xc0f8, 0x4702, { 0x83, 0x01, 0x4f, 0xc2, 0xc5, 0x47, 0x0a, 0x51 }} + [Ppis] ## Include/Ppi/ArmMpCoreInfo.h gArmMpCoreInfoPpiGuid = { 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} } diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index fa275db1381d..e716dac50417 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -106,6 +106,15 @@ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf ArmFfaLib|ArmPkg/Library/ArmFfaLib/ArmFfaPeiLib.inf +[LibraryClasses.common.MM_CORE_STANDALONE] + StandaloneMmCoreEntryPoint|ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf + HobLib|StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf + +[LibraryClasses.common.MM_STANDALONE] + StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf + HobLib|StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf + MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf + [Components.common] ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf @@ -166,6 +175,12 @@ ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf +[Components.common.MM_CORE_STANALONE] + ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf + +[Components.common.MM_STANDALONE] + ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf + [Components.AARCH64] ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c b/ArmPkg/Drivers/StandaloneMmCpu/EventHandle.c similarity index 100% rename from StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c rename to ArmPkg/Drivers/StandaloneMmCpu/EventHandle.c diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c b/ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c similarity index 100% rename from StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c rename to ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c diff --git a/StandaloneMmPkg/Include/StandaloneMmCpu.h b/ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h similarity index 100% rename from StandaloneMmPkg/Include/StandaloneMmCpu.h rename to ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf b/ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf similarity index 93% rename from StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf rename to ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf index 36b70ba1b9f8..dcf94d5778d7 100644 --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf +++ b/ArmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf @@ -19,10 +19,12 @@ ENTRY_POINT = StandaloneMmCpuInitialize [Sources] - StandaloneMmCpu.c EventHandle.c + StandaloneMmCpu.c + StandaloneMmCpu.h [Packages] + ArmPkg/ArmPkg.dec MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec StandaloneMmPkg/StandaloneMmPkg.dec diff --git a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h b/ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h similarity index 100% rename from StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h rename to ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h diff --git a/StandaloneMmPkg/Include/Protocol/PiMmCpuDriverEp.h b/ArmPkg/Include/Protocol/PiMmCpuDriverEp.h similarity index 100% rename from StandaloneMmPkg/Include/Protocol/PiMmCpuDriverEp.h rename to ArmPkg/Include/Protocol/PiMmCpuDriverEp.h diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint64.S b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/AArch64/ModuleEntryPoint.S similarity index 100% rename from StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint64.S rename to ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/AArch64/ModuleEntryPoint.S diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint32.S b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint.S similarity index 100% rename from StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint32.S rename to ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/Arm/ModuleEntryPoint.S diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c similarity index 96% rename from StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c rename to ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c index f5d2361c5f5f..5e33999a9e84 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c +++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c @@ -22,12 +22,11 @@ #include -#include - #include #include #include +#include #include #include #include diff --git a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf new file mode 100644 index 000000000000..9afd8e971546 --- /dev/null +++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf @@ -0,0 +1,72 @@ +## @file +# Module entry point library for DXE core. +# +# Copyright (c) 2024, Arm Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = ArmStandaloneMmCoreEntryPoint + FILE_GUID = 16d7b2e4-a025-11ef-8931-6b032fa329a6 + MODULE_TYPE = MM_CORE_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + LIBRARY_CLASS = StandaloneMmCoreEntryPoint|MM_CORE_STANDALONE + +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + ArmStandaloneMmCoreEntryPoint.c + SetPermissions.c + +[Sources.AARCH64] + AArch64/ModuleEntryPoint.S + +[Sources.ARM] + Arm/ModuleEntryPoint.S + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[Packages] + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + StandaloneMmMmuLib + ArmSvcLib + ArmTransferListLib + ArmFfaLib + +[Guids] + gMpInformationHobGuid + gEfiMmPeiMmramMemoryReserveGuid + gEfiStandaloneMmNonSecureBufferGuid + gEfiHobListGuid + +[Protocols] + gEdkiiPiMmCpuDriverEpProtocolGuid + gEfiMmCommunication2ProtocolGuid + +[Pcd] + gArmTokenSpaceGuid.PcdStMmStackSize + +# +# This configuration fails for CLANGPDB, which does not support PIE in the GCC +# sense. Such however is required for ARM family StandaloneMmCore +# self-relocation, and thus the CLANGPDB toolchain is unsupported for ARM and +# AARCH64 for this module. +# +[BuildOptions] + GCC:*_*_ARM_CC_FLAGS = -fpie + GCC:*_*_AARCH64_CC_FLAGS = -fpie diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c similarity index 96% rename from StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c rename to ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c index 5c6bd0e1d7d2..fd3fdae4f086 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c +++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c @@ -13,7 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include -#include +#include #include #include #include diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf index 14d42258e79f..9f66a8f84c09 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf @@ -21,16 +21,6 @@ # VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) # -[Sources.AARCH64, Sources.ARM] - Arm/StandaloneMmCoreEntryPoint.c - Arm/SetPermissions.c - -[Sources.AARCH64] - Arm/ModuleEntryPoint64.S - -[Sources.ARM] - Arm/ModuleEntryPoint32.S - [Sources.X64] X64/StandaloneMmCoreEntryPoint.c @@ -39,34 +29,15 @@ MdeModulePkg/MdeModulePkg.dec StandaloneMmPkg/StandaloneMmPkg.dec -[Packages.ARM, Packages.AARCH64] - ArmPkg/ArmPkg.dec - [LibraryClasses] BaseLib DebugLib -[LibraryClasses.ARM, LibraryClasses.AARCH64] - StandaloneMmMmuLib - ArmSvcLib - ArmTransferListLib - ArmFfaLib - [Guids] gMpInformationHobGuid gEfiMmPeiMmramMemoryReserveGuid gEfiStandaloneMmNonSecureBufferGuid -[Guids.ARM, Guids.AARCH64] - gEfiHobListGuid - -[Protocols.ARM, Protocols.AARCH64] - gEdkiiPiMmCpuDriverEpProtocolGuid - gEfiMmCommunication2ProtocolGuid - -[FixedPcd.ARM, FixedPcd.AARCH64] - gArmTokenSpaceGuid.PcdStMmStackSize - # # This configuration fails for CLANGPDB, which does not support PIE in the GCC # sense. Such however is required for ARM family StandaloneMmCore diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec index bc4286c36bdf..17629218952a 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dec +++ b/StandaloneMmPkg/StandaloneMmPkg.dec @@ -33,11 +33,6 @@ [LibraryClasses.X64.PEIM] MmPlatformHobProducerLib|Include/Library/MmPlatformHobProducerLib.h -[LibraryClasses.AArch64, LibraryClasses.ARM] - ## @libraryclass Defines a set of interfaces for the MM core entrypoint for - ## AArch64 and ARM. - StandaloneMmCoreEntryPoint|Include/Library/Arm/StandaloneMmCoreEntryPoint.h - [Guids] gStandaloneMmPkgTokenSpaceGuid = { 0x18fe7632, 0xf5c8, 0x4e63, { 0x8d, 0xe8, 0x17, 0xa5, 0x5c, 0x59, 0x13, 0xbd }} gMpInformationHobGuid = { 0xba33f15d, 0x4000, 0x45c1, { 0x8e, 0x88, 0xf9, 0x16, 0x92, 0xd4, 0x57, 0xe3 }} @@ -51,9 +46,6 @@ gEventMmDispatchGuid = { 0x7e6efffa, 0x69b4, 0x4c1b, { 0xa4, 0xc7, 0xaf, 0xf9, 0xc9, 0x24, 0x4f, 0xee }} -[Protocols] - gEdkiiPiMmCpuDriverEpProtocolGuid = { 0x6ecbd5a1, 0xc0f8, 0x4702, { 0x83, 0x01, 0x4f, 0xc2, 0xc5, 0x47, 0x0a, 0x51 }} - [PcdsFixedAtBuild, PcdsPatchableInModule] ## Maximum permitted encapsulation levels of sections in a firmware volume, # in the MM phase. Minimum value is 1. Sections nested more deeply are rejected. diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc index dcffeb27250f..2dcd6a685693 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dsc +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc @@ -56,7 +56,6 @@ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf - StandaloneMmCoreEntryPoint|StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf HobPrintLib|MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf @@ -72,8 +71,12 @@ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf +[LibraryClasses.X64] + StandaloneMmCoreEntryPoint|StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf + [LibraryClasses.AARCH64, LibraryClasses.ARM] ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf + StandaloneMmCoreEntryPoint|ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf @@ -135,7 +138,6 @@ # StandaloneMmPkg/Core/StandaloneMmCore.inf StandaloneMmPkg/Library/FvLib/FvLib.inf - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf @@ -148,10 +150,11 @@ StandaloneMmPkg/Library/StandaloneMmExtractGuidedSectionLib/StandaloneMmExtractGuidedSectionLib.inf [Components.AARCH64, Components.ARM] - StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf + ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf [Components.X64] + StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf ###################################################################################################