From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 1B6DBD8007D for ; Thu, 28 Mar 2024 12:30:21 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=6ETEQXwcJe/nYYxbSoQivNTiJDNNU4h8VZce823QkdQ=; c=relaxed/simple; d=groups.io; h=Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Received-SPF:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20240206; t=1711629020; v=1; b=ZfuGSkGW988L4+gan5NYhcF0bCNKy4853PsfoTPz/56CjHq4Cb0Cf2LtxSao+CR9OQwv0jp3 WgI3CajW7c1/xQhUh5Q19IuRkoGWtLMKtyrGHZ6rvLDBnUEEd31tXDUUoNQbImcTd20q8A3Es+C PXgLCouS86JYhf2DuoP/3V7Zi+vL2hbezZvXUULCvqGxBzexMp5+7OvL+Gr2xZkdk7ahhasLmGC BItZFvkHSeCfJLCr1yjBYdj5equd0hRTN7kWtH2PmXHpfgo7uN9IRRLRp8n4n/tvyUxIJqRbN8q K6aRyaYUla+gKDztibEMZ8wVbvsvl9e/YbCSkWrDNKqtA== X-Received: by 127.0.0.2 with SMTP id K4PWYY7687511xxf0myB63ZI; Thu, 28 Mar 2024 05:30:20 -0700 X-Received: from NAM12-DM6-obe.outbound.protection.outlook.com (NAM12-DM6-obe.outbound.protection.outlook.com [40.107.243.56]) by mx.groups.io with SMTP id smtpd.web10.14584.1711629018512574896 for ; Thu, 28 Mar 2024 05:30:18 -0700 X-Received: from BL0PR01CA0017.prod.exchangelabs.com (2603:10b6:208:71::30) by DM4PR12MB8499.namprd12.prod.outlook.com (2603:10b6:8:181::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7409.31; Thu, 28 Mar 2024 12:30:15 +0000 X-Received: from MN1PEPF0000F0DF.namprd04.prod.outlook.com (2603:10b6:208:71:cafe::9c) by BL0PR01CA0017.outlook.office365.com (2603:10b6:208:71::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7409.13 via Frontend Transport; Thu, 28 Mar 2024 12:30:15 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C X-Received: from SATLEXMB03.amd.com (165.204.84.17) by MN1PEPF0000F0DF.mail.protection.outlook.com (10.167.242.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7409.10 via Frontend Transport; Thu, 28 Mar 2024 12:30:15 +0000 X-Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Thu, 28 Mar 2024 07:30:14 -0500 X-Received: from BLR-LAB-SFW01.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35 via Frontend Transport; Thu, 28 Mar 2024 07:30:13 -0500 From: "Abdul Lateef Attar via groups.io" To: CC: Abdul Lateef Attar , Sami Mujawar , Pierre Gondois Subject: [edk2-devel] [PATCH v4 3/5] DynamicTablesPkg: Adds ACPI WSMT Table generator Date: Thu, 28 Mar 2024 17:59:57 +0530 Message-ID: <493c01a03d29c4224ad4f87d4c6560fee423c67f.1711625281.git.AbdulLateef.Attar@amd.com> In-Reply-To: References: MIME-Version: 1.0 Received-SPF: None (SATLEXMB03.amd.com: AbdulLateef.Attar@amd.com does not designate permitted sender hosts) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0DF:EE_|DM4PR12MB8499:EE_ X-MS-Office365-Filtering-Correlation-Id: aa9a1654-fd70-4ded-3d15-08dc4f22d238 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: mCLt9m7bYtW25yZ5J6DkRZriXRPnimWTIfNU9VRN1NMubMxEf63Wb1sc3BL0oBfa/hEXiC7NMi31KGwklFTYTzdkJgOF+jNa0vMB8IFDazFnnhvgspFHsHV7t8jKOrc3kNLqQweraCJ9Z9tDzf03rC+67A7i+DyDid8quYkMaGmQkRYi+43Q26EdEjfn1cZhYZzo4UVjDRsIvxyHI5BKb19YsIkSheplqkYW+7NmeXwticLl58MnB4n5ONUS7qxbTOb8r2Ou5pRUlzgMkfBxPkFLWyA4d8lLWPY8qkZ+aUI96X7OSut+ttM5864I8pl+ZtoVIVkRlc7qVOQSVW86K8isHdVOZCm1V+YZz0AJMa2H8dEx8R9zFcBoV8NfMY+tcndG44bXQsTIR8VSvGoOjyFsuCj2tIdj7eS+Y79hixehYidCRT1540Z+2JMjrhR6bQABJpOMwpIVZGb3M5GX+RgICwb1uy5/6RJsxUNxXL9arags65zPCNCqNfb3gc+OjBd5BDisfrIeQDRqYrnF8glpCwxUVER4EZ9fT286TDEa23NeSOls6Fte2PLXwfhAW/ac3D27J/x4g+kDzYzvtqtoGLK+PI3AT2udZ6FsOsG2evF6kfejxqk35ZNsKjUrn+qQROlw4RRRGXslKYg1f0EmbBZW1+5Cp21anLy7L+ipZW9KZ1ffqs6FScK/TrPJt+3di2eyajcxroB+5Rpxbw== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Mar 2024 12:30:15.3682 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: aa9a1654-fd70-4ded-3d15-08dc4f22d238 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0DF.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB8499 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Thu, 28 Mar 2024 05:30:18 -0700 Reply-To: devel@edk2.groups.io,AbdulLateef.Attar@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: 9Wd68MTvjG6H6nT4VkQK40fEx7686176AA= Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=ZfuGSkGW; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=pass (policy=none) header.from=groups.io Adds generic ACPI WSMT table generator library. Register/Deregister WSMT table. Update the WSMT table during boot as per specification. Cc: Sami Mujawar Cc: Pierre Gondois Signed-off-by: Abdul Lateef Attar --- DynamicTablesPkg/DynamicTables.dsc.inc | 2 + DynamicTablesPkg/Include/AcpiTableGenerator.h | 1 + .../Include/ArchNameSpaceObjects.h | 11 + .../Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf | 30 +++ .../Library/Acpi/AcpiWsmtLib/WsmtGenerator.c | 243 ++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.i= nf create mode 100644 DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/WsmtGenerator= .c diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dyna= micTables.dsc.inc index b2ef36eb8a..477dc6b6a9 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -35,6 +35,7 @@ # DynamicTablesPkg/Library/Acpi/AcpiFadtLib/AcpiFadtLib.inf DynamicTablesPkg/Library/Acpi/AcpiHpetLib/AcpiHpetLib.inf + DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf =20 [Components.IA32, Components.X64] # @@ -44,6 +45,7 @@ NULL|DynamicTablesPkg/Library/Acpi/AcpiFadtLib/AcpiFadtLib.inf NULL|DynamicTablesPkg/Library/Acpi/AcpiHpetLib/AcpiHpetLib.inf + NULL|DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf } =20 [Components.ARM, Components.AARCH64] diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesP= kg/Include/AcpiTableGenerator.h index 18b5f99f47..a32ef46ecb 100644 --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h @@ -100,6 +100,7 @@ typedef enum StdAcpiTableId { EStdAcpiTableIdSsdtPciExpress, ///< SSDT Pci Express Gene= rator EStdAcpiTableIdPcct, ///< PCCT Generator EStdAcpiTableIdHpet, ///< HPET Generator + EStdAcpiTableIdWsmt, ///< WSMT Generator EStdAcpiTableIdMax } ESTD_ACPI_TABLE_ID; =20 diff --git a/DynamicTablesPkg/Include/ArchNameSpaceObjects.h b/DynamicTable= sPkg/Include/ArchNameSpaceObjects.h index b90e573a88..8b16056ba1 100644 --- a/DynamicTablesPkg/Include/ArchNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/ArchNameSpaceObjects.h @@ -40,6 +40,7 @@ typedef enum ArchObjectID { EArchObjFadtHypervisorVendorId, ///< 12 - Hypervisor vendor identity inf= ormation EArchObjFadtMiscInfo, ///< 13 - Legacy fields; RTC, latency, f= lush stride, etc EArchObjHpetBaseAddress, ///< 14 - HPET Base Address + EArchObjWsmtProtectionFlags, ///< 15 - WSMT protection flags EArchObjMax } E_ARCH_OBJECT_ID; =20 @@ -223,4 +224,14 @@ typedef struct CmArchFadtMiscInfo { typedef struct CmArchHpetBaseAddress { UINT64 BaseAddress; } CM_ARCH_HPET_BASE_ADDRESS; + +/** A structure that describes the + protection flags for the WSMT fields information. + + ID: EArchObjWsmtProtectionFlags +*/ +typedef struct CmArchWsmtProtectionFlags { + UINT32 ProtectionFlags; +} CM_ARCH_WSMT_PROTECTION_FLAGS; + #endif diff --git a/DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf b/Dy= namicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf new file mode 100644 index 0000000000..80ddaf0ab4 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf @@ -0,0 +1,30 @@ +## @file +# WSMT Table Generator +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 1.27 + BASE_NAME =3D AcpiWsmtLib + FILE_GUID =3D D6C34086-C914-4F8E-B56A-08329B4D1271 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D NULL|DXE_DRIVER + CONSTRUCTOR =3D AcpiWsmtLibConstructor + DESTRUCTOR =3D AcpiWsmtLibDestructor + +[Sources] + WsmtGenerator.c + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + diff --git a/DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/WsmtGenerator.c b/Dy= namicTablesPkg/Library/Acpi/AcpiWsmtLib/WsmtGenerator.c new file mode 100644 index 0000000000..a63b4b4859 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/WsmtGenerator.c @@ -0,0 +1,243 @@ +/** @file + WSMT Table Generator + + Copyright (c) 2017 - 2023, Arm Limited. All rights reserved. + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.5 Specification, Aug 29, 2022 + - WSMT spec, version 1.0, April 18, 2016 + https://msdn.microsoft.com/windows/hardware/drivers/bringup/acpi-syste= m-description-tables#wsmt + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** The Creator ID for the ACPI tables generated using + the standard ACPI table generators. +*/ +#define TABLE_GENERATOR_CREATOR_ID_GENERIC SIGNATURE_32('D', 'Y', 'N', 'T= ') + +/** The AcpiWsmt is a template EFI_ACPI_WSMT_TABLE + structure used for generating the WSMT Table. +*/ +STATIC +EFI_ACPI_WSMT_TABLE mAcpiWsmt =3D { + ACPI_HEADER ( + EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE, + EFI_ACPI_WSMT_TABLE, + EFI_WSMT_TABLE_REVISION + ), + EFI_WSMT_PROTECTION_FLAGS_SYSTEM_RESOURCE_PROTECTION| \ + EFI_WSMT_PROTECTION_FLAGS_COMM_BUFFER_NESTED_PTR_PROTECTION| \ + EFI_WSMT_PROTECTION_FLAGS_FIXED_COMM_BUFFERS +}; + +/** This macro expands to a function that retrieves the + protection flags information for WSMT Table. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArch, + EArchObjWsmtProtectionFlags, + CM_ARCH_WSMT_PROTECTION_FLAGS + ); + +/** Construct the WSMT 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 t= he + requested object. +**/ +STATIC +EFI_STATUS +BuildWsmtTable ( + 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; + CM_ARCH_WSMT_PROTECTION_FLAGS *ProtectionFlags; + + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (Table !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: WSMT: Requested table revision =3D %d, is not supported." + "Supported table revision: Minimum =3D %d, Maximum =3D %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table =3D NULL; + + Status =3D AddAcpiHeader ( + CfgMgrProtocol, + This, + (EFI_ACPI_DESCRIPTION_HEADER *)&mAcpiWsmt, + AcpiTableInfo, + sizeof (EFI_ACPI_WSMT_TABLE) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: WSMT: Failed to add ACPI header. Status =3D %r\n", + Status + )); + return Status; + } + + Status =3D GetEArchObjWsmtProtectionFlags ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ProtectionFlags, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: WSMT: Failed to get protection flags information." \ + " Status =3D %r\n", + Status + )); + } else { + mAcpiWsmt.ProtectionFlags =3D ProtectionFlags->ProtectionFlags; + } + + /// Sanity check WSMT Projection Flags + if ((mAcpiWsmt.ProtectionFlags & EFI_WSMT_PROTECTION_FLAGS_COMM_BUFFER_N= ESTED_PTR_PROTECTION) !=3D 0) { + if ((mAcpiWsmt.ProtectionFlags & EFI_WSMT_PROTECTION_FLAGS_FIXED_COMM_= BUFFERS) =3D=3D 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: WSMT: Protection flags are invalid. " \ + "COMM_BUFFER_NESTED_PTR_PROTECTION is set but FIXED_COMM_BUFFERS i= s not set.\n" + )); + return EFI_INVALID_PARAMETER; + } + } + + *Table =3D (EFI_ACPI_DESCRIPTION_HEADER *)&mAcpiWsmt; + + return Status; +} + +/** This macro defines the WSMT Table Generator revision. +*/ +#define WSMT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the WSMT Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR mWsmtGenerator =3D { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdWsmt), + // Generator Description + L"ACPI.STD.WSMT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_WSMT_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_WSMT_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_GENERIC, + // Creator Revision + WSMT_GENERATOR_REVISION, + // Build Table function + BuildWsmtTable, + // No additional resources are allocated by the generator. + // Hence the Free Resource function is not required. + NULL, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** 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 +AcpiWsmtLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D RegisterAcpiTableGenerator (&mWsmtGenerator); + DEBUG ((DEBUG_INFO, "WSMT: Register Generator. Status =3D %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 +AcpiWsmtLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D DeregisterAcpiTableGenerator (&mWsmtGenerator); + DEBUG ((DEBUG_INFO, "WSMT: Deregister Generator. Status =3D %r\n", Statu= s)); + ASSERT_EFI_ERROR (Status); + return Status; +} --=20 2.34.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#117206): https://edk2.groups.io/g/devel/message/117206 Mute This Topic: https://groups.io/mt/105195462/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-