From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (EUR05-AM6-obe.outbound.protection.outlook.com [40.107.22.45]) by mx.groups.io with SMTP id smtpd.web12.9838.1633103015554388801 for ; Fri, 01 Oct 2021 08:43:36 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@armh.onmicrosoft.com header.s=selector2-armh-onmicrosoft-com header.b=I52ltQUJ; spf=pass (domain: arm.com, ip: 40.107.22.45, mailfrom: sami.mujawar@arm.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=jUCvdF+iru8l4AvV2y53WVT6/f1hQs5n3eYdLe72/zk=; b=I52ltQUJhsyEm+kZShIqUQ6QSk8jqlfu8uMgA9kxowTjaSQGIcjcwhaIteRsmXPMGn2ck6B5Lz9eP/U0GFBEoeNe2TOSq46/8kXOSpQcYwtcMO79/o3iTJqO3K7H7LauqWsu614MNByAlqYRTQEA9xg6c/RgUgFPqqEhyYV6/dI= Received: from AM6P194CA0028.EURP194.PROD.OUTLOOK.COM (2603:10a6:209:90::41) by DB8PR08MB4971.eurprd08.prod.outlook.com (2603:10a6:10:ed::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4544.15; Fri, 1 Oct 2021 15:43:24 +0000 Received: from VE1EUR03FT052.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:90:cafe::6d) by AM6P194CA0028.outlook.office365.com (2603:10a6:209:90::41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.14 via Frontend Transport; Fri, 1 Oct 2021 15:43:24 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; edk2.groups.io; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;edk2.groups.io; dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT052.mail.protection.outlook.com (10.152.19.173) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.14 via Frontend Transport; Fri, 1 Oct 2021 15:43:24 +0000 Received: ("Tessian outbound ab2dc3678fa9:v103"); Fri, 01 Oct 2021 15:43:23 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: b3c4aa8a9ae81e76 X-CR-MTA-TID: 64aa7808 Received: from 48599aa0a537.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id BA78404A-C8D2-40EE-AA35-064EB161F8FC.1; Fri, 01 Oct 2021 15:43:07 +0000 Received: from EUR04-DB3-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 48599aa0a537.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Fri, 01 Oct 2021 15:43:07 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FB45zOTSx57Z6BZJJm/vcUgipzbNNWCmsLd9X/LkR1qfSqz7DKVw1Ngf+epZH3ExC2bjCP5Rwk+JpNJiKm0vKZTGVjVwGs8BSG5tdSWJeV5IxXiMZpKHmy86fhZ0dtAFReP8GCwveJ/hggBTx6UZGlvaf5vYQHcrEbry3MRhGi1v+B8fROjmqnJATnFarbB2m1M7xI60W6aDCMEcM+uQoonoGHIEO7AYlt4yH5YL66LwxPRHEBEvllDiyK17IzUbOdraXsxVfYF7L9bLB88r5lz0MVbRCgQ2AB1f7vGmLhDw48R+H4Y3/E7v7hpGWGHij008ojNrjnr2+EDdOpM6Bg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=jUCvdF+iru8l4AvV2y53WVT6/f1hQs5n3eYdLe72/zk=; b=BfUiZbKTTOYk5hyn36L40jTyusqtMk5vRVtX4i2p7oPRWGCAWcTgv3dNa3nIP52DeYVkfObCWLgcku43uSIGv5E7xIqND24r6R+AhAOeryax4cChnhIE25A5rNzCrwL0L1PzEF7wiBrhpFh6eoN6U3/b4qQdWQKQmfb24tvOQyWi8tVZehB6cIHgKtf/358WHJrnShrdhqL9UePZmdxHJ2IixVcFKNJigviTytZbWWB/WTsUQXlofccMWaLnqMBnS26v7RFZwgWnZBuCT3f5yar7Z/Dp5H6UEyWm8WR+6YsKY9BWpAw86N/lXNWHGvNb02qcYJTJqdvMOsVq43YNYw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=jUCvdF+iru8l4AvV2y53WVT6/f1hQs5n3eYdLe72/zk=; b=I52ltQUJhsyEm+kZShIqUQ6QSk8jqlfu8uMgA9kxowTjaSQGIcjcwhaIteRsmXPMGn2ck6B5Lz9eP/U0GFBEoeNe2TOSq46/8kXOSpQcYwtcMO79/o3iTJqO3K7H7LauqWsu614MNByAlqYRTQEA9xg6c/RgUgFPqqEhyYV6/dI= Authentication-Results-Original: arm.com; dkim=none (message not signed) header.d=none;arm.com; dmarc=none action=none header.from=arm.com; Received: from AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) by AM6PR08MB4470.eurprd08.prod.outlook.com (2603:10a6:20b:b5::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.14; Fri, 1 Oct 2021 15:43:05 +0000 Received: from AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::c8a5:672a:9ff2:e554]) by AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::c8a5:672a:9ff2:e554%6]) with mapi id 15.20.4566.019; Fri, 1 Oct 2021 15:43:05 +0000 Subject: Re: [PATCH v1 11/13] DynamicTablesPkg: AML code generation to add an _LPI state To: Pierre.Gondois@arm.com, devel@edk2.groups.io, Alexei Fedorov Cc: Akanksha Jain , Alexandru Elisei , nd References: <20210623114039.24491-1-Pierre.Gondois@arm.com> <20210623114039.24491-13-Pierre.Gondois@arm.com> From: "Sami Mujawar" Message-ID: Date: Fri, 1 Oct 2021 16:43:05 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.0.1 In-Reply-To: <20210623114039.24491-13-Pierre.Gondois@arm.com> X-ClientProxiedBy: LO4P123CA0184.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:1a4::9) To AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) MIME-Version: 1.0 Received: from [10.1.196.43] (217.140.106.52) by LO4P123CA0184.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:1a4::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.14 via Frontend Transport; Fri, 1 Oct 2021 15:43:04 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 068d41ec-96ed-4d88-3a7a-08d984f23449 X-MS-TrafficTypeDiagnostic: AM6PR08MB4470:|DB8PR08MB4971: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2582;OLM:2582; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: iskwRxaKDDSIA1IRljMPTBDtypVC/iHF9LFZuM+/HduHZbYgJO8MMm92/WljF2duIh2yksLf9Fi8CvlNTw2KTX5eZRblbiMxSOS5tjrFZOXGrcDvuYayqqPyCJOjaca0tz6aKNSDP5JVApa9E49MUW3O402Xe/2huhbi1/11ryaTHZmFGmdbjZzbH+OI/0DisDP7eCQbCaXfDgbOQ14rnqAcfnNwvL1gww+ZOpIkStJYG290UIhKx4BDhBUGcqRKnZbbmr1tyQVFEYVf/7RL9ZoTwXb4ijWbRMwtBGkwta1zAWy5Z66hqnfPJhQ3n3EI42AWwtJQERlN3EDnwYVvqJx+iC1RkhsdyvYUvHgMOx0DdHrh26TAAe7UFbPVNBlC+6hl27hIXE/DHIo+Q6bracVO6zC6gBlbdww2mAWzFFxcXSOIQCwNqScfpIrUTC+r8bTTPPcKOD3uw6kpJns/DgqzPTHHFuYXInIEz8OyYaz1rwINFyALLZwEbeZ9G1XArcsWqoOjhtHLu9fBStgTOCZPGYo1Pkfuz2RbamPh0RCzbpY1FovcVaVNGWwSGs71zl1ROmZvkrs+Dn5cv+7XQ9WX2u4QzDrmalwu5r4Q7UxJknsaQeXhU5dbxIUuA77qxFsKZ8Uvm0ODxqZ1NQgagsrQG1CvSQLwoR2UGT2Ryg+eB4fq0kBRVh1iiOgyQjoPcqcdB4ssEvRD9tYyzXkFLNdFOOTANyC6GIp5p0YBe/fGSLB8iq+M6otyHAxa0MT+1NfxhVMcTm5x7UipJrJYSA== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AS8PR08MB6806.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6636002)(956004)(6486002)(2616005)(44832011)(30864003)(26005)(53546011)(8936002)(33964004)(38100700002)(37006003)(66476007)(31696002)(16576012)(66946007)(8676002)(86362001)(2906002)(6862004)(36756003)(38350700002)(66556008)(54906003)(83380400001)(186003)(52116002)(508600001)(19627235002)(316002)(4326008)(5660300002)(31686004)(43740500002)(45980500001)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB4470 Original-Authentication-Results: arm.com; dkim=none (message not signed) header.d=none;arm.com; dmarc=none action=none header.from=arm.com; Return-Path: Sami.Mujawar@arm.com X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT052.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 3f96302f-6254-48d2-60d6-08d984f228a5 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 55elQffaN2dKPkRELsrC7YcEYSVCogEHdTK1kShEP3CTzizZCd/prCIFxpXLasFSXRfkJ9xohXVO4btIMMyV7Z4uv5OpVF+PDgis4LtzKAUpfKDG99QHFbdWYwo83rw2YjqruhQpIsrJGj4s8N4BN6pRLFbJAcnPDGz+tnll4BS7KyYZmsavFVa4qieH9kN5hQ0rUHmcqQG8lacmUj4G7GRh2if1EyxoXFNbAblCApWZXJbAuZ+HKMH8A2WJHs1laOnNBxDbRM5RifRXvZTqcGdbxqJ2p/DvMyb1VN9t9xi8EdEy1vlbSvwXIQEGO1bLlIT5NIGt9dfSvMjk7vENTCFFjT+zaaRRU6GURmIRQ35ljxCXChqW1vn3Jv94egbNzd4JrGiWRVo/2u9TGiML1fCgHUINSZRiy0ishtDQRwsBmH3rIoMdxMRncD4e6taZH1iw9bMf68BjzZ4rNkxOrHFvaxiGzhChHbpibLeKWFLvg/JDP5/Lgxoaubqz46pmtF7HkgDhc0ajXx3zFYMd/bnFO/VggHW51XcJhTsiZihOazMCmtMl7sJ6hE0GKfkRCzxbW68GtZM5+NM8Ug9gU4OocRGy9mrDXbRQMHwIPlBjg77MZMK2L4nTU9k7ogYiuQd9mLpzjjw2YXPeJr5Tf7WaTMwvmTQdAucPuLkWL9G5LJoKvvaJ9ugjOmNwnfa7ko9HR3kun/b/ZS5qiX/ms8WxL+260dtt4W94j4JldQc= X-Forefront-Antispam-Report: CIP:63.35.35.123;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:64aa7808-outbound-1.mta.getcheckrecipient.com;PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com;CAT:NONE;SFS:(4636009)(46966006)(36840700001)(36860700001)(508600001)(6486002)(8936002)(33964004)(2906002)(6636002)(81166007)(356005)(53546011)(82310400003)(36756003)(31696002)(83380400001)(6862004)(31686004)(16576012)(2616005)(54906003)(70206006)(4326008)(186003)(26005)(956004)(8676002)(44832011)(47076005)(19627235002)(70586007)(316002)(336012)(30864003)(86362001)(37006003)(5660300002)(43740500002)(579004);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Oct 2021 15:43:24.2422 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 068d41ec-96ed-4d88-3a7a-08d984f23449 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d;Ip=[63.35.35.123];Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: VE1EUR03FT052.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB4971 Content-Type: multipart/alternative; boundary="------------0148C24535317BE6CA18153A" Content-Language: en-GB --------------0148C24535317BE6CA18153A Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Hi Pierre, Please find my response inline marked [SAMI]. Regards, Sami Mujawar On 23/06/2021 12:40 PM, Pierre.Gondois@arm.com wrote: > From: 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 > }, > > Signed-off-by: Pierre Gondois > --- > .../Include/Library/AmlLib/AmlLib.h | 71 +++ > .../Common/AmlLib/CodeGen/AmlCodeGen.c | 439 ++++++++++++++++++ > 2 files changed, 510 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 89350f65f5df..f0861040191f 100644 > --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c > +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c > @@ -12,6 +12,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -1554,3 +1555,441 @@ 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; > + > + // Get the LPI value which is represented as a PackageOp object node > + // which is the 2nd fixed argument (i.e. index 1). > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + goto error_handler; > + } > + Status = AmlCodeGenRdRegister ( > + GenericRegisterDescriptor->AddressSpaceId, > + GenericRegisterDescriptor->RegisterBitWidth, > + GenericRegisterDescriptor->RegisterBitOffset, > + GenericRegisterDescriptor->Address, > + GenericRegisterDescriptor->AccessSize, > + NULL, > + &RdNode > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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); > + 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_2_0_SYSTEM_MEMORY, > + 0, > + 0, > + 0, > + 0, > + NULL, > + &RdNode > + ); > + } > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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_2_0_SYSTEM_MEMORY, [SAMI] Can we useEFI_ACPI_6_4_SYSTEM_MEMORY here instead? > + 0, > + 0, > + 0, > + 0, > + NULL, > + &RdNode > + ); > + } > + if (EFI_ERROR (Status)) { > + ASSERT (0); > + 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); > + 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; > +} --------------0148C24535317BE6CA18153A Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 7bit

Hi Pierre,

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 23/06/2021 12:40 PM, Pierre.Gondois@arm.com wrote:
From: Pierre Gondois <Pierre.Gondois@arm.com>

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
  },

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
---
 .../Include/Library/AmlLib/AmlLib.h           |  71 +++
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 439 ++++++++++++++++++
 2 files changed, 510 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 89350f65f5df..f0861040191f 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>
@@ -1554,3 +1555,441 @@ 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;
+
+  // Get the LPI value which is represented as a PackageOp object node
+  // which is the 2nd fixed argument (i.e. index 1).
+  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);
+    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);
+    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);
+    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);
+    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);
+    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);
+    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);
+      goto error_handler;
+    }
+    Status = AmlCodeGenRdRegister (
+               GenericRegisterDescriptor->AddressSpaceId,
+               GenericRegisterDescriptor->RegisterBitWidth,
+               GenericRegisterDescriptor->RegisterBitOffset,
+               GenericRegisterDescriptor->Address,
+               GenericRegisterDescriptor->AccessSize,
+               NULL,
+               &RdNode
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      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);
+      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);
+    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_2_0_SYSTEM_MEMORY,
+               0,
+               0,
+               0,
+               0,
+               NULL,
+               &RdNode
+               );
+  }
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    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);
+    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_2_0_SYSTEM_MEMORY,
[SAMI] Can we use EFI_ACPI_6_4_SYSTEM_MEMORY here instead?
+               0,
+               0,
+               0,
+               0,
+               NULL,
+               &RdNode
+               );
+  }
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    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);
+    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;
+}

--------------0148C24535317BE6CA18153A--