From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64078+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 159724577680861.477071880005155; Wed, 12 Aug 2020 08:22:56 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id zOeWYY1788612xXgHjkFCVww; Wed, 12 Aug 2020 08:22:56 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.74]) by mx.groups.io with SMTP id smtpd.web12.16958.1597245773370046603 for ; Wed, 12 Aug 2020 08:22:54 -0700 X-Received: from AM5PR04CA0022.eurprd04.prod.outlook.com (2603:10a6:206:1::35) by AM4PR0802MB2291.eurprd08.prod.outlook.com (2603:10a6:200:5e::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.15; Wed, 12 Aug 2020 15:22:50 +0000 X-Received: from AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com (2603:10a6:206:1:cafe::e0) by AM5PR04CA0022.outlook.office365.com (2603:10a6:206:1::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:22:50 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64078+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT022.mail.protection.outlook.com (10.152.16.79) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:50 +0000 X-Received: ("Tessian outbound 7161e0c2a082:v64"); Wed, 12 Aug 2020 15:22:50 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 010c66c1c1d07c52 X-CR-MTA-TID: 64aa7808 X-Received: from 48a1904769b1.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 37231928-3F89-4D80-82F5-81E55BBC51F4.1; Wed, 12 Aug 2020 15:22:44 +0000 X-Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 48a1904769b1.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:22:44 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hSjPyEQeQE4n68Ie/w2FXTQ+S9P1L0ZGMeJbZxInhORmo1GJVMmXpYrrw7FV//EC+hs0HkZzBHq6N5NgUb7GS8imtVMWoAfcvmJcUpOKTeFrNgb3pTIyiNG7xn+I6fbn6qokRETQ46XPjr/gXczpA2k4OvSpWWlrYzTZKHwq3N6XfnbtKbTuPVEpm0yiAgv2MWWRp22/TGPXBvUSu9F6Y3jFHh5Onu9ju7a3nA7rQyN8nYOQrU5JA9yjAIMy2poYab7jRMeekLHx7f9qYIvCcuxXT7sJki/N0p0/tUloRsIeR8TuVjC6jEonzLVgnZnizVLZHDV3IulhLfNN4hwVHg== 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-SenderADCheck; bh=rFjnrro4uiX/r/U1ubUCMYMVMSX86+uuT/P87nQvUIY=; b=VcvrG8rFLk0xSZyu2bxIVhI8qDNXZz1XkgQvA3AXoMNKQh1EOZOFUhwLeLaiXs6LiVJw2N51wMs958PfGuTOb5ngPi8vEf1aqrDJVpHwjVjIbvQ5ZdEBmuiec2Iizz4CvIlCr6Qzea6aJSPXI40pSzJQBPEHhl+6TUsGCpcUN1f0dXCCJl8CbknJNy5OZO5W9vf25t5muMc/KZbxVLqyJeD6dpDBNlg1VmOdv5ButmIb2Keqt13aLDdz5XGPDX1Ot3UEu0+CViQioKNySpU7DXEU4iBdIAI/d9KNeX91DFRY1CoU89246/dWlFCfrxB/7taEY5soepbU7pLDdOrbMg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB8PR06CA0012.eurprd06.prod.outlook.com (2603:10a6:10:100::25) by VI1PR0802MB2222.eurprd08.prod.outlook.com (2603:10a6:800:9b::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:22:42 +0000 X-Received: from DB5EUR03FT005.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:100:cafe::7b) by DB8PR06CA0012.outlook.office365.com (2603:10a6:10:100::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:22:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT005.mail.protection.outlook.com (10.152.20.122) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:42 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:22:41 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:22:37 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 01/30] DynamicTablesPkg: Introduction to Dynamic AML Date: Wed, 12 Aug 2020 16:22:07 +0100 Message-ID: <20200812152236.31164-2-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f77cff8f-72c8-4925-a811-08d83ed39356 X-MS-TrafficTypeDiagnostic: VI1PR0802MB2222:|AM4PR0802MB2291: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:9508;OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: innqBEzAfRc12gRlqMScGwQfZok+hHYQ+KPBLvHNfc2g3m9Osx+0eXGt1L00WEcuU/j5M+k5pDZMxNsBPoaSKonqFukRNnKxRFA3MbLIZe+FbIX9wx2eMeTXDZMuCafYH9CWiskx4rssEJCfIB86OxZdN77n4fBj9ylI7WdEYGSEby4nMDWMQGRIH7fRBKLGEh6Eicl2VRb8mTUfnnT64Nzp5iWfsmNmI+v3x7/LahuS9Na7u1Cku3T0jZ8XkV4J9a8V+2faFHypSRvMkzkaB72XS5UU0gawxi/rVABvqP8kGvSRuJZ5FqFlzaauVabGOM9DHoRYad0gg8aj6O4XsguGifXsFbR36lmQOhPcaaS3HkUEPSSTMiBV7tHD5o9dO+sWagQ7pLDXVYDgIG8S2zba7FJq3mCObRx55cbl+dBcQrlWgGSSKeP1jzeY4HAc4wpzy8Z/Mzo8/dkBOEQeNqiSxj5J1HSJc1FWaf9YTZc= X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(346002)(376002)(396003)(136003)(39860400002)(46966005)(5660300002)(478600001)(8936002)(86362001)(7696005)(26005)(8676002)(186003)(2906002)(336012)(83380400001)(81166007)(356005)(2616005)(44832011)(82310400002)(47076004)(1076003)(6666004)(70586007)(6916009)(36756003)(4326008)(82740400003)(426003)(316002)(70206006)(54906003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0802MB2222 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: cd0d8960-6416-4dec-9852-08d83ed38e91 X-Microsoft-Antispam-Message-Info: /I1mDL7bdPHLHuLehKMD0SOxNr3QUwI5AQmTSxiCExU5S9NLd0k6TSL7fuBD7WCkCPANkeB3jLqHRWuDn48ufmvmBbZaJbw/Y0MVgsYEs9jjuAe3HSDd23Q6bkTD99btWyHsbLD1M8jGsehg28LouuL8RtM20nR2Qcd+VNMcdIfi3OVPna2iGvdu7Bi7IQdJnRBpIZvO6rFIBe6NQkKDwtdcVTQq7YXYptOxZO4f7v87FpXujN6lGvLvTp/pClTfY+A6MjHgkH8f7ac02ZLvKrDmiXpCmBSoyZDsoQCm/l0Uo78/VBxk0ylzeU44WYncxcR2r0OlcreRnVoR6t6gwSmxtUSE17VzATSmGAWcuStnbE4sREyDTrKW3HS+yLgLXFiBlUmMO0P46ycDThYdMmAOoIfvtUMvWjn/Xx4/WBJDQ2t7OxSQDHMr/vYcJzSg/3bs9hDUfNqB6AStkrj0M+ruS9IWLKznwxs1bChMp+o= X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:22:50.3096 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f77cff8f-72c8-4925-a811-08d83ed39356 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: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0802MB2291 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 8td5Z0oniMiCvcYJHd5uNzCBx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245776; bh=ik0sy7S7V4sz6J31syTMp+96Jl7t/8+5V/Ufr7T2fYU=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=Mc5DZCVd6mjcr42IMmFT3Qjd5xZYKybUW6m0xf1fVJ+9nxKWRvkhboERampkTKrh2V/ hw8SpSMHvFzcGYgPA7bFYkp3NgHBCE/E5ly08QgMtp4Ob5eEdpOCv2pte1a2N8S8KQLTA URMGXHhOQ2+e3jdIrOqERdadGEKRLyZyp3U= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" ACPI Definition block (e.g. DSDT or SSDT) tables are implemented using ACPI source language (ASL) and compiled to ACPI Machine language (AML). The AML bytecode runs in the OS ACPI Interpreter. AML has a complex grammar which makes generation of ACPI Definition block tables difficult. Dynamic Tables Framework introduces a new feature 'Dynamic AML' that aims at simplifying the generation of ACPI Definition block tables. Dynamic AML provides the following techniques for generating ACPI Definition blocks. - AML Fixup - AML Codegen - AML Fixup + Codegen AML Fixup involves patching an AML template code at runtime and then installing the fixed-up AML code as an ACPI table. AML Codegen provides APIs to generate small segments of AML code that can be serialised for installation as an ACPI table. AML Fixup + Codegen is an approach where parts of an AML template are fixed-up at runtime as well as the AML Codegen APIs are used to insert small segments of AML code in the AML template. This AML code is then serialised for installation as an ACPI table. To assist Dynamic AML generation an AmlLib library is introduced that provides a rich set of APIs that can be used to parse, traverse, fixup, codegen and serialise AML definition blocks. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Readme.md | 128 +++++++++++++++++--- 1 file changed, 111 insertions(+), 17 deletions(-) diff --git a/DynamicTablesPkg/Readme.md b/DynamicTablesPkg/Readme.md index 34000cf73bc7da5fce2e520d41318af908353969..5f92d4c6cb2efd77bbc3306f827= 088216b7a32e0 100644 --- a/DynamicTablesPkg/Readme.md +++ b/DynamicTablesPkg/Readme.md @@ -1,5 +1,4 @@ -Dynamic Tables Framework ------------------------- +# Dynamic Tables Framework =20 Dynamic Tables Framework provides mechanisms to reduce the amount of effort required in porting firmware to new platforms. The aim is @@ -10,8 +9,8 @@ be generated from the system construction. This initial r= elease does not fully implement that - the configuration is held in local UEFI modules. =20 -Feature Summary ---------------- +# Feature Summary + The dynamic tables framework is designed to generate standardised firmware tables that describe the hardware information at run-time. A goal of standardised firmware is to have a common @@ -58,8 +57,105 @@ The framework currently supports the following table ge= nerators for ARM: * SSDT - Secondary System Description Table. This is essentially a RAW table generator. =20 -Roadmap -------- +## Dynamic AML + +ACPI Definition block (e.g. DSDT or SSDT) tables are used to describe syst= em +devices along with other control and power management information. These t= ables +are written using ACPI Source Language (ASL). The ASL code is compiled usi= ng an +ASL compiler (e.g. Intel iASL compiler) to generate ACPI Machine Language = (AML) +bytecode. + +Since, definition blocks are represented using AML grammar, run-time gener= ation +of definition blocks is complex. Dynamic AML is a feature of Dynamic Tables +framework that provides a solution for dynamic generation of ACPI Definiti= on +block tables. + +Dynamic AML introduces the following techniques: +* AML Fixup +* AML Codegen +* AML Fixup + Codegen + +### AML Fixup +AML fixup is a technique that involves compiling an ASL template file to +generate AML bytecode. This template AML bytecode can be parsed at run-time +and a fixup code can update the required fields in the AML template. + +To simplify AML Fixup, the Dynamic Tables Framework provides an *AmlLib* +library with a rich set of APIs that can be used to fixup the AML code. + +### AML Codegen +AML Codegen employs generating small segments of AML code. The *AmlLib* +library provides AML Codegen APIs that generate the AML code segments. + + Example: The following table depicts the AML Codegen APIs and the + corresponding ASL code that would be generated. + + | AML Codegen API | ASL Code | + |--------------------------------|--------------------------------| + | AmlCodeGenDefinitionBlock ( | DefinitionBlock ( | + | .., | ... | + | &RootNode); | ) { | + | AmlCodeGenScope ( | Scope (_SB) { | + | "\_SB", | | + | RootNode, | | + | &ScopeNode); | | + | AmlCodeGenDevice ( | Device (CPU0) { | + | "CPU0", | | + | ScopeNode, | | + | &CpuNode); | | + | AmlCodeGenNameString ( | Name (_HID, "ACPI0007") | + | "_HID", | | + | "ACPI0007", | | + | CpuNode, | | + | &HidNode); | | + | AmlCodeGenNameInteger ( | Name (_UID, Zero) | + | "_UID", | | + | 0, | | + | CpuNode, | | + | &UidNode); | | + | | } // Device | + | | } // Scope | + | | } // DefinitionBlock | + +### AML Fixup + Codegen +A combination of AML Fixup and AML Codegen could be used for generating +Definition Blocks. For example the AML Fixup could be used to fixup certain +parts of the AML template while the AML Codegen APIs could be used to inse= rted +small fragments of AML code in the AML template. + +### AmlLib Library +Since, AML bytecode represents complex AML grammar, an **AmlLib** library = is +introduced to assist parsing and traversing of the AML bytecode at run-tim= e. + +The AmlLib library parses a definition block and represents it as an AML +tree. This tree representation is based on the AML grammar defined by the +ACPI 6.3 specification, section - 20 'ACPI Machine Language (AML) +Specification'. + +AML objects, methods and data are represented as tree nodes. Since the AML +data is represented as tree nodes, it is possible to traverse the tree, lo= cate +a node and modify the node data. The tree can then be serialized to a buff= er +(that represents the definition block). This definition block containing +the fixed up AML code can then be installed as an ACPI table (DSDT/SSDT). + +AmlLib provides a rich API to operate on AML data. For example it provides +APIs to update a device's name, the value of a "_UID" object, and the memo= ry +and interrupt number stored in a "_CRS" node. + +Although the AmlLib performs checks to a reasonable extent while modifying= a +definition block, these checks may not cover all aspects due to the comple= xity +of the ASL/AML language. It is therefore recommended to review any operati= on +performed, and validate the generated output. + + Example: The serialized AML code could be validated by + - Saving the generated AML to a file and comparing with + a reference output. + or + - Disassemble the generated AML using the iASL compiler + and verifying the output. + +# Roadmap + The current implementation of the Configuration Manager populates the platform information statically as a C structure. Further enhancements to introduce runtime loading of platform information from a platform @@ -68,13 +164,13 @@ information file is planned. Also support for generating SMBIOS tables is planned and will be added subsequently. =20 -Supported Platforms -------------------- +# Supported Platforms + 1. Juno 2. FVP Models =20 -Build Instructions ------------------- +# Build Instructions + 1. Set path for the iASL compiler with support for generating a C header file as output. =20 @@ -102,15 +198,14 @@ or >build -a AARCH64 -p Platform\ARM\VExpressPkg\ArmVExpress-FVP-AArch64.dsc -t GCC5 **-D DYNAMIC_TABLES_FRAMEWORK** =20 -Prerequisites -------------- +# Prerequisites + Ensure that the latest ACPICA iASL compiler is used for building *Dynamic = Tables Framework*. *Dynamic Tables Framework* has been tested using the following iASL compil= er version: -[Version 20200717](https://www.acpica.org/node/183)*, dated 17 July, 2020. +[Version 20200717](https://www.acpica.org/node/183), dated 17 July, 2020. =20 =20 -Running CI builds locally -------------------------- +#Running CI builds locally =20 The TianoCore EDKII project has introduced Core CI infrastructure using Ti= anoCore EDKII Tools PIP modules: =20 @@ -178,8 +273,7 @@ The instructions to setup the CI environment are in *'e= dk2\\.pytool\\Readme.md'* - use `stuart_build -c .pytool/CISettings.py -h` option to see help on= additional options. =20 =20 -Documentation -------------- +# Documentation =20 Refer to the following presentation from *UEFI Plugfest Seattle 2018*: =20 --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64078): https://edk2.groups.io/g/devel/message/64078 Mute This Topic: https://groups.io/mt/76149132/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64080+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245786171110.80543785053169; Wed, 12 Aug 2020 08:23:06 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id wEy7YY1788612xJcRObonEGJ; Wed, 12 Aug 2020 08:23:05 -0700 X-Received: from EUR01-HE1-obe.outbound.protection.outlook.com (EUR01-HE1-obe.outbound.protection.outlook.com [40.107.13.80]) by mx.groups.io with SMTP id smtpd.web12.16960.1597245781876937863 for ; Wed, 12 Aug 2020 08:23:02 -0700 X-Received: from AM5PR04CA0006.eurprd04.prod.outlook.com (2603:10a6:206:1::19) by DBBPR08MB4361.eurprd08.prod.outlook.com (2603:10a6:10:c8::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:22:59 +0000 X-Received: from AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com (2603:10a6:206:1:cafe::65) by AM5PR04CA0006.outlook.office365.com (2603:10a6:206:1::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:59 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64080+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT022.mail.protection.outlook.com (10.152.16.79) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:59 +0000 X-Received: ("Tessian outbound 7161e0c2a082:v64"); Wed, 12 Aug 2020 15:22:58 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 301679b47698f026 X-CR-MTA-TID: 64aa7808 X-Received: from 683ef5d74b3f.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 035022A6-05DC-4B3E-8D09-5D3E9E21F108.1; Wed, 12 Aug 2020 15:22:53 +0000 X-Received: from EUR02-AM5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 683ef5d74b3f.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:22:53 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NBSyaHP4H9resy8gflC9ya4y/YbnV4QNOJNgdP93pReWS7aDURHgTfF0i/EPDxlr7JdnVBpiMoxqNPqiNhXU/MkQsl3BnZicMcqaaEZtuWIPKTjOVhf4o8MDDVlNc61UnUXBcz8kJ2UBqtQ57fLXHHf2P4Wlu41mt0GFZEiRo9EKNm9Q9byvBhjAdqDreyxoMVYrlQO0mR0e7j0FFDQk52FlxgAmDl3lSP2QN5L3+BHlHEYNkaefeZelo3qEY7jgcPSB2wsrKrKiPwVSW9+qbouNGhU648WoHbGn3yFw6xvKBxH293R+cRvjIM6viPwLwYGnwo0z3E/52UdvvS3tzg== 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-SenderADCheck; bh=eXwElLQbNmONyNKVHduRqkrXGG12ab5/G8o9s8yhYZg=; b=TRXfx2uyNXHE541or6t4Kg+b538Z1kjaf7qtnJ61utd00GEluGznRmupGY07oDCEQMq6ffnMZa12hUlXTX5b1TXHDPxGHYwA004+peJfDFVDXZ68EjJn/EC17hBxB1punGjjyOGdOonGnPtB+pxeWZt/j6e3M4qlrzJ0n9B0S2eI5/AwKNIsiAaB01A+wRBop304UWYc0+PDRurbQqwy3wkC7Y3IhLqu2axhYJTsR9W8xRvcn2M2primFTILQlgpdaR6aBYBV9OEzW7j621tBeysdq74b2R9OvdHz0Towm/AhCogGHdgaZLvl6fhir6IEBjm+NYUkJ//DYobhe5T7w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB8PR06CA0014.eurprd06.prod.outlook.com (2603:10a6:10:100::27) by DB7PR08MB3817.eurprd08.prod.outlook.com (2603:10a6:10:77::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.17; Wed, 12 Aug 2020 15:22:52 +0000 X-Received: from DB5EUR03FT005.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:100:cafe::56) by DB8PR06CA0014.outlook.office365.com (2603:10a6:10:100::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:22:51 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT005.mail.protection.outlook.com (10.152.20.122) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:51 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:22:43 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:22:41 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:22:41 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 02/30] DynamicTablesPkg: AmlLib definitions Date: Wed, 12 Aug 2020 16:22:08 +0100 Message-ID: <20200812152236.31164-3-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: eaf5e734-46d6-4efc-a1c8-08d83ed39886 X-MS-TrafficTypeDiagnostic: DB7PR08MB3817:|DBBPR08MB4361: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:9508;OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: PfHjn3FAWpsGhFnl6P1EztbkgaS5NMDRSeWsHHQ/doQeDJEKa0t0MVsvWK8cwlrIllE7sSbKRZqIDd2Q5vomhBZJm6qSxpPnGjW5lUqlJFNBL61edLcUct8Wgz9ijDBE7LighmW5dJ2vC4D8hOjOfNaucyLXR51pci879+4AbvhD9eHohUjg6MjQPr43apRqwdniO78rkUd+LivtthvUvu3d0UT03/YfSCqb+r4wuP9wjlZYV1amPe3MJrLUjAboSJTa1m4ir81WqXw8wyIQvOeggdI+lx0SXhQMD3bbXEzaQKGzgbXhF0yvZkOA1o4YFWzgUB7Sm9mdx4tCslmMbs52hzC+wMxkM+5cBtpZp4+WegQcHMdn5yYTQVSY5Dr7SPGOnAsfbYKb6TCoenmumw== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(376002)(39860400002)(346002)(396003)(136003)(46966005)(2616005)(2906002)(82740400003)(70206006)(26005)(36756003)(83380400001)(6666004)(356005)(186003)(4326008)(70586007)(81166007)(316002)(426003)(1076003)(86362001)(54906003)(8676002)(7696005)(5660300002)(478600001)(82310400002)(47076004)(8936002)(336012)(6916009)(44832011)(19627235002);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3817 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 4ee07bb0-cda5-4b60-340a-08d83ed393f0 X-Microsoft-Antispam-Message-Info: cmwnGhgwkm5qRojyaE2Y0Dj+WOar+6Jb/UVfSkh5doiZZK2j/2Q1RciJtlv+tj4MMHubesJN/oLgogQCEa4r2LHD68d3QljZ2+sdsE17C7823ieGaxPjlAUBv/X9/qlIudT9pKaeeKMAw1PBASMN8OWdNIrI45yUtzym5KqEcLee2/lU9dk/XApD2AW+kTnkdqK5Jfs0s+puBRNh/gQ9Lo85mHdgjeSXzld+Iy69Rn6QVlmNZ4KgmTnm/+JCTkdL32OzRHnpQ8AOIkvM3ABawGfO2VffwXiRvwxKd0MEGWVMPwPBBwaAgZijVjI6yKs86ttbUE6Xr9lB/bVgnoNHtYUQG0G49nVHahVejI6OIM/xsgY+8RATh948AbqR+i1u2A8nXjK7nYVZLTaMxgpDwA== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:22:59.0127 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: eaf5e734-46d6-4efc-a1c8-08d83ed39886 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: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4361 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: UK5y6cDRs224rA8l62o0prqbx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245785; bh=lOopPtLqGhMeQQJOipjlEWxprw662xkVEv8HN4MY9fg=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=muFJX2JWJmb4r2xyRk+teWD1fiA2CkvCY1Rm72Tzz5arSSZEK10e0bs4glITALSazBs 5kPdwzz6JlkXsgtRs6PX7ZRZheH6/vJUfebQDVUWxmpnMshXLx74ypEjPk4tLHQYObMKd ATwBk7Z9ku82H0Zp6NdvjmAnEyWPGFPjcBo= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Dynamic AML is a solution to generate Definition Block tables at runtime. Dynamic AML provides the following techniques for generating AML tables. - AML Fixup - AML Codegen - AML Fixup + Codegen AML fixup involves patching small sections of a template AML code at runtime, while AML Codegen provides APIs to generate small sections of AML code at runtime. A combination of Fixup and Codegen can also be used. AML has a complex grammar. To simplify the generation of AML tables, Dynamic AML introduces AmlLib that provides a rich set of APIs for parsing, traversing, fixup, codegen and serialisation of AML byte code. This patch introduces the definitions used by AmlLib. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h | 188 ++++++++++++++++= ++++ DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h | 18 ++ 2 files changed, 206 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h b/DynamicT= ablesPkg/Library/Common/AmlLib/AmlDefines.h new file mode 100644 index 0000000000000000000000000000000000000000..cbae14d78802005c9b7610e8085= a484610e8b18f --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h @@ -0,0 +1,188 @@ +/** @file + AML Defines. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_DEFINES_H_ +#define AML_DEFINES_H_ + +/** + @defgroup TreeStructures Tree structures + @ingroup AMLLib + @{ + The AML tree created by the AMLLib relies on enum/define values and + structures defined here. + @} +*/ + +/** AML tree node types. + + Data nodes are tagged with the data type they contain. + Some data types cannot be used for data nodes (None, Object). + EAmlUIntX types are converted to the EAML_NODE_DATA_TYPE enum type. + These types are accessible externally. + + @ingroup TreeStructures +*/ +typedef enum EAmlNodeDataType { + EAmlNodeDataTypeNone =3D 0, ///< EAmlNone, not accessible. + EAmlNodeDataTypeReserved1, ///< EAmlUInt8, converted to the UInt= type. + EAmlNodeDataTypeReserved2, ///< EAmlUInt16, converted to the UInt= type. + EAmlNodeDataTypeReserved3, ///< EAmlUInt32, converted to the UInt= type. + EAmlNodeDataTypeReserved4, ///< EAmlUInt64, converted to the UInt= type. + EAmlNodeDataTypeReserved5, ///< EAmlObject, not accessible. + EAmlNodeDataTypeNameString, ///< EAmlName, name corresponding to t= he + /// NameString keyword in the ACPI + /// specification. E.g.: "\_SB_.DEV0" + EAmlNodeDataTypeString, ///< EAmlString, NULL terminated strin= g. + EAmlNodeDataTypeUInt, ///< Integer data of any length, EAmlU= IntX + /// are converted to this type. + EAmlNodeDataTypeRaw, ///< Raw bytes contained in a buffer. + EAmlNodeDataTypeResourceData, ///< Resource data element. + EAmlNodeDataTypeFieldPkgLen, ///< FieldPkgLen data element. + /// PkgLen are usually stored as + /// part of object node structures. + /// However, they can be found + /// standalone in a FieldList. + EAmlNodeDataTypeMax ///< Max enum. +} EAML_NODE_DATA_TYPE; + +/** Indexes of fixed arguments. + + AML objects defined the ACPI 6.3 specification, + s20.3 "AML Byte Stream Byte Values" can have at most 6 fixed arguments. + + Method and functions can have at most 7 arguments, cf + s19.6.83 "Method (Declare Control Method)". The enum goes to 8 to store = the + name of the method invocation. + + @ingroup TreeStructures +*/ +typedef enum EAmlParseIndex { + EAmlParseIndexTerm0 =3D 0, ///< First fixed argument index. + EAmlParseIndexTerm1, ///< Second fixed argument index. + EAmlParseIndexTerm2, ///< Third fixed argument index. + EAmlParseIndexTerm3, ///< Fourth fixed argument index. + EAmlParseIndexTerm4, ///< Fifth fixed argument index. + EAmlParseIndexTerm5, ///< Sixth fixed argument index. + EAmlParseIndexMax ///< Maximum fixed argument index (=3D6). +} EAML_PARSE_INDEX; + +/** Maximum size of an AML NameString. + + An AML NameString can be at most (255 * 4) + 255 + 2 =3D 1277 bytes long. + Indeed, according to ACPI 6.3 specification, s20.2.2, + an AML NameString can be resolved as a MultiNamePath. + + The encoding of this MultiNamePath can be made of at most: + - 255 carets ('^'), one for each level in the namespace; + - 255 NameSeg of 4 bytes; + - 2 bytes for the MultiNamePrefix and SegCount. + + @ingroup TreeStructures +*/ +#define MAX_AML_NAMESTRING_SIZE 1277U + +/** Maximum size of an ASL NameString. + + An ASL NameString can be at most (255 * 4) + 255 + 254 =3D 1529 bytes lon= g. + Cf the ASL grammar available in ACPI 6.3 specification, 19.2.2. + + The encoding of an ASL NameString can be made of at most: + - 255 carets ('^'), one for each level in the namespace; + - 255 NameSeg of 4 bytes; + - 254 NameSeg separators ('.'). + + @ingroup TreeStructures +*/ +#define MAX_ASL_NAMESTRING_SIZE 1529U + +/** Pseudo OpCode for method invocations. + + The AML grammar does not attribute an OpCode/SubOpCode couple for + method invocations. This library is representing method invocations + as if they had one. + + The AML encoding for method invocations in the ACPI specification 6.3 is: + MethodInvocation :=3D NameString TermArgList + In this library, it is: + MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount Term= ArgList + ArgumentCount :=3D ByteData + + When computing the size of a tree or serializing it, the additional data= is + not taken into account (i.e. the MethodInvocationOp and the ArgumentCoun= t). + + @ingroup TreeStructures +*/ +#define AML_METHOD_INVOC_OP 0xD0 + +/** Pseudo OpCode for NamedField field elements. + + The AML grammar does not attribute an OpCode/SubOpCode couple for + the NamedField field element. This library is representing NamedField fi= eld + elements as if they had one. + + The AML encoding for NamedField field elements in the ACPI specification= 6.3 + is: + NamedField :=3D NameSeg PkgLength + In this library, it is: + NamedField :=3D NamedFieldOp NameSeg PkgLength + + When computing the size of a tree or serializing it, the additional data= is + not taken into account (i.e. the NamedFieldOp). + + @ingroup TreeStructures +*/ +#define AML_FIELD_NAMED_OP 0x04 + +/** Size of a NameSeg. + Cf. ACPI 6.3 specification, s20.2. + + @ingroup TreeStructures +*/ + #define AML_NAME_SEG_SIZE 4U + +/** AML object types. + + The ACPI specification defines several object types. They are listed + with the definition of ObjectTypeKeyword. + + @ingroup TreeStructures +*/ +typedef enum EAmlObjType { + EAmlObjTypeUnknown =3D 0x0, + EAmlObjTypeInt, + EAmlObjTypeStrObj, + EAmlObjTypeBuffObj, + EAmlObjTypePkgObj, + EAmlObjTypeFieldUnitObj, + EAmlObjTypeDeviceObj, + EAmlObjTypeEventObj, + EAmlObjTypeMethodObj, + EAmlObjTypeMutexObj, + EAmlObjTypeOpRegionObj, + EAmlObjTypePowerResObj, + EAmlObjTypeProcessorObj, + EAmlObjTypeThermalZoneObj, + EAmlObjTypeBuffFieldObj, + EAmlObjTypeDDBHandleObj, +} EAML_OBJ_TYPE; + +/** Node types. + + @ingroup TreeStructures +*/ +typedef enum EAmlNodeType { + EAmlNodeUnknown, ///< Unknown/Invalid AML Node Type. + EAmlNodeRoot, ///< AML Root Node, typically represents a DefinitionB= lock. + EAmlNodeObject, ///< AML Object Node, typically represents an ASL stat= ement + /// or its arguments. + EAmlNodeData, ///< AML Data Node, typically represents arguments for= an + /// ASL statement. + EAmlNodeMax ///< Max enum. +} EAML_NODE_TYPE; + +#endif // AML_DEFINES_H_ diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h b/DynamicT= ablesPkg/Library/Common/AmlLib/AmlInclude.h new file mode 100644 index 0000000000000000000000000000000000000000..274482f0d1244cdabc5436c5542= a2b829083ae93 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h @@ -0,0 +1,18 @@ +/** @file + AML Include file + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_INCLUDE_H_ +#define AML_INCLUDE_H_ + +#include +#include +#include +#include +#include + +#endif // AML_INCLUDE_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64080): https://edk2.groups.io/g/devel/message/64080 Mute This Topic: https://groups.io/mt/76149135/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64081+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245793224452.54411746314884; Wed, 12 Aug 2020 08:23:13 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 1QFOYY1788612xfuuYUuec50; Wed, 12 Aug 2020 08:23:12 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.43]) by mx.groups.io with SMTP id smtpd.web12.16964.1597245789185941780 for ; Wed, 12 Aug 2020 08:23:10 -0700 X-Received: from AM5PR0202CA0005.eurprd02.prod.outlook.com (2603:10a6:203:69::15) by AM5PR0801MB1841.eurprd08.prod.outlook.com (2603:10a6:203:2e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:03 +0000 X-Received: from VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:69:cafe::72) by AM5PR0202CA0005.outlook.office365.com (2603:10a6:203:69::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:03 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64081+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT014.mail.protection.outlook.com (10.152.19.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:03 +0000 X-Received: ("Tessian outbound e8cdb8c6f386:v64"); Wed, 12 Aug 2020 15:23:03 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 443c5b3e43d73ebc X-CR-MTA-TID: 64aa7808 X-Received: from 76a67ba2aef0.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 5FCD4F29-3607-4373-ABDE-05BBDE7632BA.1; Wed, 12 Aug 2020 15:22:57 +0000 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 76a67ba2aef0.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:22:57 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=I0i7d8c+8KZxIFA5w2FOL52hVXkbMfxszd1EOP0ifO3PVWoPLF6viHZmRXb7NVh6gIhXI+Crde/HmXXuvD8piaS029q9eDBszoDtTix+1S3Ys+usZXtWxoRBZF+345GD2iFJ4E4ft+juNplkNkHAC3VVFdeFxgGAJ2cL98/CpQJZipPxzxroNp3MS+UyO5M68qxhX6nuVwd5eL7wIB12KuWN4w4QjHEi1OjJFix5GVZO3QIP6KS5Yqg5NWtCEua6/dH5BDdGb+IK8xJVoXgOWO/MH2yooPwbA3AAja37ksJrNryihOLQgSS6s6MNkGz27JhTy4ZNsl04mx0ZK8/viA== 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-SenderADCheck; bh=VoY1qBouIVRGXd+hipioXu7bPqswDy3q8yGIc6Te0RQ=; b=HD8vuN34RpB5402xYy4he2Gw+S/Dc7ILaDzvAN0rghkBHOjToCjekubZUi/rv9+8Tk7hIEk/6qLPcxSEdAZYTkhbknxsDz41VMDdl2LXnJfLdsqXW69F0prOfvBRTxTE+QUkowwP5Bl3c8DpuuHqtWN1h0YL+pCKVe9/fLSi5lwHv8xOxCJvnkfvUJow7G+NHhJAgKro4bUP88vY04CyxJ3FBPE34jmNDq00H1/Cwl1jvhCTMPxwQSLhy3pk6IcX+gXB5PXYdj4UobSgdl8TIpXPqPie3P/JqnuDO3FsCtixu8xoXZxG869Lcgt7bn7zDVAmltbHTMzeJfS1qhB0Jg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR0301CA0064.eurprd03.prod.outlook.com (2603:10a6:4:54::32) by AM0PR08MB3297.eurprd08.prod.outlook.com (2603:10a6:208:66::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.17; Wed, 12 Aug 2020 15:22:53 +0000 X-Received: from DB5EUR03FT060.eop-EUR03.prod.protection.outlook.com (2603:10a6:4:54:cafe::79) by DB6PR0301CA0064.outlook.office365.com (2603:10a6:4:54::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:53 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT060.mail.protection.outlook.com (10.152.21.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:53 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:22:43 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:22:43 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 03/30] DynamicTablesPkg: AML grammar definition Date: Wed, 12 Aug 2020 16:22:09 +0100 Message-ID: <20200812152236.31164-4-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5e7d1b26-f96d-454d-dac8-08d83ed39b19 X-MS-TrafficTypeDiagnostic: AM0PR08MB3297:|AM5PR0801MB1841: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:10000;OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: 37xzUdO5gNtzq2NpS0NseOHAxRgRO8W0Ndpl43ury86+76QWP3ZAEQnk99+Aij6kPOn4mz1oWo4y/HLsAnbaHUG57aM/N2aH6Mxccb8XgwZx1tRKn12lANwFPLRXxxMZVkHM0yDQYaYPHgLCN3b5isxZi4BHY6pjcQAbl28tZYbyLG344LXzKxtxdSvtkSuj/9APLtNnPRTHMYELsR8zCS63mFa845CI2a7GA2V83mB7CP3U1zq7/SnhrBTwULRQxqGuMeUtPedBwPd660tNYWEeZnnZxIxzh4wumHk4BPL/F+GlfQQm4qFIMzpdHgQ21VGv5efz1yw/LRxRIsek+c9V7J5uCLGlr2VsZ7+r3fJtCHhXM/cTrdiFOlsb2P1vRq45i4UPrV3fV69JRu7hCg== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(346002)(376002)(39860400002)(396003)(136003)(46966005)(36756003)(70586007)(356005)(4326008)(6666004)(316002)(70206006)(83380400001)(186003)(81166007)(26005)(2906002)(54906003)(1076003)(6916009)(2616005)(82740400003)(7696005)(426003)(5660300002)(44832011)(82310400002)(478600001)(8936002)(30864003)(86362001)(8676002)(47076004)(336012)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB3297 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: e176be2b-4ccf-4200-d3d9-08d83ed39562 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:03.2480 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5e7d1b26-f96d-454d-dac8-08d83ed39b19 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: VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1841 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: yugmVYeAnEhdo9FGC2BfQTjyx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245792; bh=/UgOzzcCVLxK0WpX/Pmp2tycRgizsi08CSudlmvgxAM=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=B0+ywuVKHi3iJrVKzmXYgXIvNnxnT0/qJDierF49/LOfQw6fXyiZknV8W/wCNd5v6dc hXeI2MECIqrR8VEIaylFEMG4So9vxhgXOMACCKtTUBumHUtDjo+bWywzXtFNeYHchKbV8 cZOtUvO2yqa9iRW3p6Y/8rk4R6uLKhq5Ndg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois ASL is a source language for defining ACPI objects including writing ACPI control methods. An ASL file is compiled using an ASL compiler tool to generate ACPI Machine Language (AML). This AML bytecode is processed by the ACPI AML interpreter that runs as part of an Operating System (OS). Both ASL and AML are declarative languages. Although they are closely related they are different languages. ASL statements declare objects. Each object has three parts, two of which can be NULL: Object :=3D ObjectType FixedList VariableList The AML grammar defines corresponding encodings that makes up the AML byte stream. This patch introduces the AML grammar definitions used by AmlLib for encoding/decoding AML byte streams. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c | 805 +++++++++++= +++++++++ DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h | 330 ++++++++ 2 files changed, 1135 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c b/Dyn= amicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c new file mode 100644 index 0000000000000000000000000000000000000000..780bdea67f6035023f0ee995095= e50f0ae35f810 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c @@ -0,0 +1,805 @@ +/** @file + AML grammar definitions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +/** AML grammar encoding table. + + The ASL language is a description language, used to define abstract + objects, like devices, thermal zones, etc. and their place in a hierarch= ical + tree. The following table stores the AML grammar definition. It can be u= sed + to parse an AML bytestream. Each line corresponds to the definition of an + opcode and what is expected to be found with this opcode. + See table 20-440 in the ACPI 6.3 specification s20.3, and the AML + grammar definitions in s20.2. + + - OpCode/SubOpCode: + An OpCode/SubOpCode couple allows to identify an object type. + The OpCode and SubOpCode are one byte each. The SubOpCode is + used when the Opcode value is 0x5B (extended OpCode). Otherwise + the SubOpcode is set to 0. If the SubOpCode is 0 in the table + below, there is no SubOpCode in the AML bytestream, only the + OpCode is used to identify the object. + + - Fixed arguments: + The fixed arguments follow the OpCode and SubOpCode. Their number + and type can be found in the table below. There can be at the most + 6 fixed arguments for an object. + Fixed arguments's type allow to know what is expected in the AML bytestr= eam. + Knowing the size of the incoming element, AML bytes can be packed and pa= rsed + accordingly. These types can be found in the same table 20-440 in the + ACPI 6.3, s20.3 specification. + E.g.: An AML object, a UINT8, a NULL terminated string, etc. + + -Attributes: + The attribute field gives additional information on each object. This can + be the presence of a variable list of arguments, the presence of a PkgLe= n, + etc. + + In summary, an AML object is described as: + OpCode [SubOpcode] [PkgLen] [FixedArgs] [VarArgs] + + OpCode {1 byte} + [SubOpCode] {1 byte. + Only relevant if the OpCode value is + 0x5B (extended OpCode prefix). + Otherwise 0. Most objects don't have one.} + [PkgLen] {Size of the object. + It has a special encoding, cf. ACPI 6.3 + specification, s20.2.4 "Package Length + Encoding". + Most objects don't have one.} + [FixedArgs[0..X]] {Fixed list of arguments. + (where X <=3D 5) Can be other objects or data (a byte, + a string, etc.). They belong to the + current AML object. + The number of fixed arguments varies acco= rding + to the object, but it is fixed for each k= ind of + object.} + [VarArgs] {Variable list of arguments. + They also belong to the current object an= d can + be objects or data. + Most objects don't have one.} + [ByteList] {This is a sub-type of a variable list of + arguments. It can only be found in buffer + objects. + A ByteList is either a list of bytes or + a list of resource data elements. Resource + data elements have specific opcodes.} + [FieldList] {This is a sub-type of a variable list of + arguments. It can only be found in Fields, + IndexFields and BankFields. + A FieldList is made of FieldElements. + FieldElements have specific opcodes.} +*/ +GLOBAL_REMOVE_IF_UNREFERENCED +STATIC +CONST +AML_BYTE_ENCODING mAmlByteEncoding[] =3D { + // Comment Str OpCode = SubOpCode MaxIndex NameIndex 0 1= 2 3 4 5 = Attribute + /* 0x00 */ {AML_DEBUG_STR ("ZeroOp") AML_ZERO_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x01 */ {AML_DEBUG_STR ("OneOp") AML_ONE_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x06 */ {AML_DEBUG_STR ("AliasOp") AML_ALIAS_OP, = 0, 2, 1, {EAmlName, E= AmlName, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x08 */ {AML_DEBUG_STR ("NameOp") AML_NAME_OP, = 0, 2, 0, {EAmlName, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x0A */ {AML_DEBUG_STR ("BytePrefix") AML_BYTE_PREFIX, = 0, 1, 0, {EAmlUInt8, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x0B */ {AML_DEBUG_STR ("WordPrefix") AML_WORD_PREFIX, = 0, 1, 0, {EAmlUInt16, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x0C */ {AML_DEBUG_STR ("DWordPrefix") AML_DWORD_PREFIX,= 0, 1, 0, {EAmlUInt32, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x0D */ {AML_DEBUG_STR ("StringPrefix") AML_STRING_PREFIX= , 0, 1, 0, {EAmlString, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x0E */ {AML_DEBUG_STR ("QWordPrefix") AML_QWORD_PREFIX,= 0, 1, 0, {EAmlUInt64, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x10 */ {AML_DEBUG_STR ("ScopeOp") AML_SCOPE_OP, = 0, 1, 0, {EAmlName, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x11 */ {AML_DEBUG_STR ("BufferOp") AML_BUFFER_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_BYTE_LIST}, + /* 0x12 */ {AML_DEBUG_STR ("PackageOp") AML_PACKAGE_OP, = 0, 1, 0, {EAmlUInt8, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ}, + /* 0x13 */ {AML_DEBUG_STR ("VarPackageOp") AML_VAR_PACKAGE_O= P, 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ}, + /* 0x14 */ {AML_DEBUG_STR ("MethodOp") AML_METHOD_OP, = 0, 2, 0, {EAmlName, E= AmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x15 */ {AML_DEBUG_STR ("ExternalOp") AML_EXTERNAL_OP, = 0, 3, 0, {EAmlName, E= AmlUInt8, EAmlUInt8, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x2E */ {AML_DEBUG_STR ("DualNamePrefix") AML_DUAL_NAME_PRE= FIX, 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x2F */ {AML_DEBUG_STR ("MultiNamePrefix") AML_MULTI_NAME_PR= EFIX, 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x41 */ {AML_DEBUG_STR ("NameChar_A") 'A', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x42 */ {AML_DEBUG_STR ("NameChar_B") 'B', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x43 */ {AML_DEBUG_STR ("NameChar_C") 'C', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x44 */ {AML_DEBUG_STR ("NameChar_D") 'D', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x45 */ {AML_DEBUG_STR ("NameChar_E") 'E', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x46 */ {AML_DEBUG_STR ("NameChar_F") 'F', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x47 */ {AML_DEBUG_STR ("NameChar_G") 'G', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x48 */ {AML_DEBUG_STR ("NameChar_H") 'H', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x49 */ {AML_DEBUG_STR ("NameChar_I") 'I', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4A */ {AML_DEBUG_STR ("NameChar_J") 'J', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4B */ {AML_DEBUG_STR ("NameChar_K") 'K', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4C */ {AML_DEBUG_STR ("NameChar_L") 'L', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4D */ {AML_DEBUG_STR ("NameChar_M") 'M', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4E */ {AML_DEBUG_STR ("NameChar_N") 'N', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x4F */ {AML_DEBUG_STR ("NameChar_O") 'O', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x50 */ {AML_DEBUG_STR ("NameChar_P") 'P', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x51 */ {AML_DEBUG_STR ("NameChar_Q") 'Q', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x52 */ {AML_DEBUG_STR ("NameChar_R") 'R', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x53 */ {AML_DEBUG_STR ("NameChar_S") 'S', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x54 */ {AML_DEBUG_STR ("NameChar_T") 'T', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x55 */ {AML_DEBUG_STR ("NameChar_U") 'U', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x56 */ {AML_DEBUG_STR ("NameChar_V") 'V', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x57 */ {AML_DEBUG_STR ("NameChar_W") 'W', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x58 */ {AML_DEBUG_STR ("NameChar_X") 'X', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x59 */ {AML_DEBUG_STR ("NameChar_Y") 'Y', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x5A */ {AML_DEBUG_STR ("NameChar_Z") 'Z', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x5B 0x01 */ {AML_DEBUG_STR ("MutexOp") AML_EXT_OP, = AML_EXT_MUTEX_OP, 2, 0, {EAmlName, E= AmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x5B 0x02 */ {AML_DEBUG_STR ("EventOp") AML_EXT_OP, = AML_EXT_EVENT_OP, 1, 0, {EAmlName, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x5B 0x12 */ {AML_DEBUG_STR ("CondRefOfOp") AML_EXT_OP, = AML_EXT_COND_REF_OF_OP, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x13 */ {AML_DEBUG_STR ("CreateFieldOp") AML_EXT_OP, = AML_EXT_CREATE_FIELD_OP,4, 3, {EAmlObject, E= AmlObject, EAmlObject, EAmlName, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x5B 0x1F */ {AML_DEBUG_STR ("LoadTableOp") AML_EXT_OP, = AML_EXT_LOAD_TABLE_OP, 6, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlObject, EAmlObject, EAml= Object}, 0}, + /* 0x5B 0x20 */ {AML_DEBUG_STR ("LoadOp") AML_EXT_OP, = AML_EXT_LOAD_OP, 2, 0, {EAmlName, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x21 */ {AML_DEBUG_STR ("StallOp") AML_EXT_OP, = AML_EXT_STALL_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x22 */ {AML_DEBUG_STR ("SleepOp") AML_EXT_OP, = AML_EXT_SLEEP_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x23 */ {AML_DEBUG_STR ("AcquireOp") AML_EXT_OP, = AML_EXT_ACQUIRE_OP, 2, 0, {EAmlObject, E= AmlUInt16, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x24 */ {AML_DEBUG_STR ("SignalOp") AML_EXT_OP, = AML_EXT_SIGNAL_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x25 */ {AML_DEBUG_STR ("WaitOp") AML_EXT_OP, = AML_EXT_WAIT_OP, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x26 */ {AML_DEBUG_STR ("ResetOp") AML_EXT_OP, = AML_EXT_RESET_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x27 */ {AML_DEBUG_STR ("ReleaseOp") AML_EXT_OP, = AML_EXT_RELEASE_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x28 */ {AML_DEBUG_STR ("FromBCDOp") AML_EXT_OP, = AML_EXT_FROM_BCD_OP, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x29 */ {AML_DEBUG_STR ("ToBCDOp") AML_EXT_OP, = AML_EXT_TO_BCD_OP, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x2A */ {AML_DEBUG_STR ("UnloadOp") AML_EXT_OP, = AML_EXT_UNLOAD_OP, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x30 */ {AML_DEBUG_STR ("RevisionOp") AML_EXT_OP, = AML_EXT_REVISION_OP, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x31 */ {AML_DEBUG_STR ("DebugOp") AML_EXT_OP, = AML_EXT_DEBUG_OP, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x32 */ {AML_DEBUG_STR ("FatalOp") AML_EXT_OP, = AML_EXT_FATAL_OP, 3, 0, {EAmlUInt8, E= AmlUInt32, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x33 */ {AML_DEBUG_STR ("TimerOp") AML_EXT_OP, = AML_EXT_TIMER_OP, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x5B 0x80 */ {AML_DEBUG_STR ("OpRegionOp") AML_EXT_OP, = AML_EXT_REGION_OP, 4, 0, {EAmlName, E= AmlUInt8, EAmlObject, EAmlObject, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x5B 0x81 */ {AML_DEBUG_STR ("FieldOp") AML_EXT_OP, = AML_EXT_FIELD_OP, 2, 0, {EAmlName, E= AmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST}, + /* 0x5B 0x82 */ {AML_DEBUG_STR ("DeviceOp") AML_EXT_OP, = AML_EXT_DEVICE_OP, 1, 0, {EAmlName, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x5B 0x83 */ {AML_DEBUG_STR ("ProcessorOp") AML_EXT_OP, = AML_EXT_PROCESSOR_OP, 4, 0, {EAmlName, E= AmlUInt8, EAmlUInt32, EAmlUInt8, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x5B 0x84 */ {AML_DEBUG_STR ("PowerResOp") AML_EXT_OP, = AML_EXT_POWER_RES_OP, 3, 0, {EAmlName, E= AmlUInt8, EAmlUInt16, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x5B 0x85 */ {AML_DEBUG_STR ("ThermalZoneOp") AML_EXT_OP, = AML_EXT_THERMAL_ZONE_OP,1, 0, {EAmlName, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE}, + /* 0x5B 0x86 */ {AML_DEBUG_STR ("IndexFieldOp") AML_EXT_OP, = AML_EXT_INDEX_FIELD_OP, 3, 0, {EAmlName, E= AmlName, EAmlUInt8, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST}, + /* 0x5B 0x87 */ {AML_DEBUG_STR ("BankFieldOp") AML_EXT_OP, = AML_EXT_BANK_FIELD_OP, 4, 0, {EAmlName, E= AmlName, EAmlObject, EAmlUInt8, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST}, + /* 0x5B 0x88 */ {AML_DEBUG_STR ("DataRegionOp") AML_EXT_OP, = AML_EXT_DATA_REGION_OP, 4, 0, {EAmlName, E= AmlObject, EAmlObject, EAmlObject, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x5C */ {AML_DEBUG_STR ("RootChar") AML_ROOT_CHAR, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x5E */ {AML_DEBUG_STR ("ParentPrefixChar") AML_PARENT_PREFIX= _CHAR, 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x5F */ {AML_DEBUG_STR ("NameChar") '_', = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_NAME_CHAR}, + /* 0x60 */ {AML_DEBUG_STR ("Local0Op") AML_LOCAL0, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x61 */ {AML_DEBUG_STR ("Local1Op") AML_LOCAL1, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x62 */ {AML_DEBUG_STR ("Local2Op") AML_LOCAL2, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x63 */ {AML_DEBUG_STR ("Local3Op") AML_LOCAL3, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x64 */ {AML_DEBUG_STR ("Local4Op") AML_LOCAL4, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x65 */ {AML_DEBUG_STR ("Local5Op") AML_LOCAL5, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x66 */ {AML_DEBUG_STR ("Local6Op") AML_LOCAL6, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x67 */ {AML_DEBUG_STR ("Local7Op") AML_LOCAL7, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x68 */ {AML_DEBUG_STR ("Arg0Op") AML_ARG0, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x69 */ {AML_DEBUG_STR ("Arg1Op") AML_ARG1, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x6A */ {AML_DEBUG_STR ("Arg2Op") AML_ARG2, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x6B */ {AML_DEBUG_STR ("Arg3Op") AML_ARG3, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x6C */ {AML_DEBUG_STR ("Arg4Op") AML_ARG4, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x6D */ {AML_DEBUG_STR ("Arg5Op") AML_ARG5, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x6E */ {AML_DEBUG_STR ("Arg6Op") AML_ARG6, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x70 */ {AML_DEBUG_STR ("StoreOp") AML_STORE_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x71 */ {AML_DEBUG_STR ("RefOfOp") AML_REF_OF_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x72 */ {AML_DEBUG_STR ("AddOp") AML_ADD_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x73 */ {AML_DEBUG_STR ("ConcatOp") AML_CONCAT_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x74 */ {AML_DEBUG_STR ("SubtractOp") AML_SUBTRACT_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x75 */ {AML_DEBUG_STR ("IncrementOp") AML_INCREMENT_OP,= 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x76 */ {AML_DEBUG_STR ("DecrementOp") AML_DECREMENT_OP,= 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x77 */ {AML_DEBUG_STR ("MultiplyOp") AML_MULTIPLY_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x78 */ {AML_DEBUG_STR ("DivideOp") AML_DIVIDE_OP, = 0, 4, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlObject, EAmlNone, EAml= None}, 0}, + /* 0x79 */ {AML_DEBUG_STR ("ShiftLeftOp") AML_SHIFT_LEFT_OP= , 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7A */ {AML_DEBUG_STR ("ShiftRightOp") AML_SHIFT_RIGHT_O= P, 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7B */ {AML_DEBUG_STR ("AndOp") AML_AND_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7C */ {AML_DEBUG_STR ("NAndOp") AML_NAND_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7D */ {AML_DEBUG_STR ("OrOp") AML_OR_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7E */ {AML_DEBUG_STR ("NorOp") AML_NOR_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x7F */ {AML_DEBUG_STR ("XOrOp") AML_XOR_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x80 */ {AML_DEBUG_STR ("NotOp") AML_NOT_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x81 */ {AML_DEBUG_STR ("FindSetLeftBitOp") AML_FIND_SET_LEFT= _BIT_OP, 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x82 */ {AML_DEBUG_STR ("FindSetRightBitOp") AML_FIND_SET_RIGH= T_BIT_OP, 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x83 */ {AML_DEBUG_STR ("DerefOfOp") AML_DEREF_OF_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x84 */ {AML_DEBUG_STR ("ConcatResOp") AML_CONCAT_RES_OP= , 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x85 */ {AML_DEBUG_STR ("ModOp") AML_MOD_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x86 */ {AML_DEBUG_STR ("NotifyOp") AML_NOTIFY_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x87 */ {AML_DEBUG_STR ("SizeOfOp") AML_SIZE_OF_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x88 */ {AML_DEBUG_STR ("IndexOp") AML_INDEX_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x89 */ {AML_DEBUG_STR ("MatchOp") AML_MATCH_OP, = 0, 6, 0, {EAmlObject, E= AmlUInt8, EAmlObject, EAmlUInt8, EAmlObject, EAml= Object}, 0}, + /* 0x8A */ {AML_DEBUG_STR ("CreateDWordFieldOp") AML_CREATE_DWORD_= FIELD_OP, 0, 3, 2, {EAmlObject, E= AmlObject, EAmlName, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x8B */ {AML_DEBUG_STR ("CreateWordFieldOp") AML_CREATE_WORD_F= IELD_OP, 0, 3, 2, {EAmlObject, E= AmlObject, EAmlName, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x8C */ {AML_DEBUG_STR ("CreateByteFieldOp") AML_CREATE_BYTE_F= IELD_OP, 0, 3, 2, {EAmlObject, E= AmlObject, EAmlName, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x8D */ {AML_DEBUG_STR ("CreateBitFieldOp") AML_CREATE_BIT_FI= ELD_OP, 0, 3, 2, {EAmlObject, E= AmlObject, EAmlName, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x8E */ {AML_DEBUG_STR ("ObjectTypeOp") AML_OBJECT_TYPE_O= P, 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x8F */ {AML_DEBUG_STR ("CreateQWordFieldOp") AML_CREATE_QWORD_= FIELD_OP, 0, 3, 2, {EAmlObject, E= AmlObject, EAmlName, EAmlNone, EAmlNone, EAml= None}, AML_IN_NAMESPACE}, + /* 0x90 */ {AML_DEBUG_STR ("LAndOp") AML_LAND_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x91 */ {AML_DEBUG_STR ("LOrOp") AML_LOR_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x92 */ {AML_DEBUG_STR ("LNotOp") AML_LNOT_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x93 */ {AML_DEBUG_STR ("LEqualOp") AML_LEQUAL_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x94 */ {AML_DEBUG_STR ("LGreaterOp") AML_LGREATER_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x95 */ {AML_DEBUG_STR ("LLessOp") AML_LLESS_OP, = 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x96 */ {AML_DEBUG_STR ("ToBufferOp") AML_TO_BUFFER_OP,= 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x97 */ {AML_DEBUG_STR ("ToDecimalStringOp") AML_TO_DEC_STRING= _OP, 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x98 */ {AML_DEBUG_STR ("ToHexStringOp") AML_TO_HEX_STRING= _OP, 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x99 */ {AML_DEBUG_STR ("ToIntegerOp") AML_TO_INTEGER_OP= , 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x9C */ {AML_DEBUG_STR ("ToStringOp") AML_TO_STRING_OP,= 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x9D */ {AML_DEBUG_STR ("CopyObjectOp") AML_COPY_OBJECT_O= P, 0, 2, 0, {EAmlObject, E= AmlObject, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x9E */ {AML_DEBUG_STR ("MidOp") AML_MID_OP, = 0, 3, 0, {EAmlObject, E= AmlObject, EAmlObject, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0x9F */ {AML_DEBUG_STR ("ContinueOp") AML_CONTINUE_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0xA0 */ {AML_DEBUG_STR ("IfOp") AML_IF_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ}, + /* 0xA1 */ {AML_DEBUG_STR ("ElseOp") AML_ELSE_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ}, + /* 0xA2 */ {AML_DEBUG_STR ("WhileOp") AML_WHILE_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ}, + /* 0xA3 */ {AML_DEBUG_STR ("NoopOp") AML_NOOP_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0xA4 */ {AML_DEBUG_STR ("ReturnOp") AML_RETURN_OP, = 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0xA5 */ {AML_DEBUG_STR ("BreakOp") AML_BREAK_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0xCC */ {AML_DEBUG_STR ("BreakPointOp") AML_BREAK_POINT_O= P, 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, + /* 0xD0 */ {AML_DEBUG_STR ("MethodInvocOp") AML_METHOD_INVOC_= OP, 0, 2, 0, {EAmlName, E= AmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_PSEUDO_OPCODE | AML_HAS_CHILD_OBJ}, + /* 0xFF */ {AML_DEBUG_STR ("OnesOp") AML_ONES_OP, = 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, 0}, +}; + +/** AML grammar encoding for field elements. + + Some AML objects are expecting a FieldList. They are referred in this li= brary + as field nodes. These objects have the following opcodes: + - FieldOp; + - IndexFieldOp; + - BankFieldOp. + In the AML grammar encoding table, they have the AML_HAS_FIELD_LIST + attribute. + + A field list is made of field elements. + According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encodi= ng", + field elements can be: + - NamedField :=3D NameSeg PkgLength; + - ReservedField :=3D 0x00 PkgLength; + - AccessField :=3D 0x01 AccessType AccessAttrib; + - ConnectField :=3D <0x02 NameString> | <0x02 BufferData>; + - ExtendedAccessField :=3D 0x03 AccessType ExtendedAccessAttrib Access= Length. + + A small set of opcodes describes field elements. They are referred in th= is + library as field opcodes. + The NamedField field element doesn't have a field opcode. A pseudo + OpCode/SubOpCode couple has been created for it. + + Field elements: + - don't have a SubOpCode; + - have at most 3 fixed arguments (6 for object opcodes, + 8 for method invocations); + - don't have variable list of arguments; + - are not part of the AML namespace, except NamedField field elements. +*/ +GLOBAL_REMOVE_IF_UNREFERENCED +STATIC +CONST +AML_BYTE_ENCODING mAmlFieldEncoding[] =3D { + // Comment Str OpCode = SubOpCode MaxIndex NameIndex 0 1= 2 3 4 5 = Attribute + /* 0x00 */ {AML_DEBUG_STR ("FieldReservedOp") AML_FIELD_RESERVE= D_OP, 0, 0, 0, {EAmlNone, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_FIELD_ELEMENT | AML_HAS_PKG_LENGTH}, + /* 0x01 */ {AML_DEBUG_STR ("FieldAccessOp") AML_FIELD_ACCESS_= OP, 0, 2, 0, {EAmlUInt8, E= AmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_FIELD_ELEMENT}, + /* 0x02 */ {AML_DEBUG_STR ("FieldConnectionOp") AML_FIELD_CONNECT= ION_OP, 0, 1, 0, {EAmlObject, E= AmlNone, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_FIELD_ELEMENT}, + /* 0x03 */ {AML_DEBUG_STR ("FieldExtAccessOp") AML_FIELD_EXT_ACC= ESS_OP, 0, 3, 0, {EAmlUInt8, E= AmlUInt8, EAmlUInt8, EAmlNone, EAmlNone, EAml= None}, AML_IS_FIELD_ELEMENT}, + /* 0x04 */ {AML_DEBUG_STR ("FieldNamed") AML_FIELD_NAMED_O= P, 0, 2, 0, {EAmlName, E= AmlFieldPkgLen, EAmlNone, EAmlNone, EAmlNone, EAml= None}, AML_IS_FIELD_ELEMENT | AML_IS_PSEUDO_OPCODE | AML_IN_NAMESPAC= E} +}; + +/** Get the AML_BYTE_ENCODING entry in the AML encoding table. + + Note: For Pseudo OpCodes this function returns NULL. + + @param [in] Buffer Pointer to an OpCode/SubOpCode couple. + If *Buffer =3D 0x5b (extended OpCode), + Buffer must be at least two bytes long. + + @return The corresponding AML_BYTE_ENCODING entry. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetByteEncoding ( + IN CONST UINT8 * Buffer + ) +{ + UINT8 OpCode; + UINT8 SubOpCode; + UINT32 Index; + + if (Buffer =3D=3D NULL) { + ASSERT (0); + return NULL; + } + + // Get OpCode and SubOpCode. + OpCode =3D Buffer[0]; + if (OpCode =3D=3D AML_EXT_OP) { + SubOpCode =3D Buffer[1]; + } else { + SubOpCode =3D 0; + } + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0])); + Index++) { + if ((mAmlByteEncoding[Index].OpCode =3D=3D OpCode) && + (mAmlByteEncoding[Index].SubOpCode =3D=3D SubOpCode)) { + if ((mAmlByteEncoding[Index].Attribute & AML_IS_PSEUDO_OPCODE) =3D= =3D + AML_IS_PSEUDO_OPCODE) { + // A pseudo OpCode cannot be parsed as it is internal to this libr= ary. + // The MethodInvocation encoding can be detected by NameSpace look= up. + ASSERT (0); + return NULL; + } + return &mAmlByteEncoding[Index]; + } + } + + return NULL; +} + +/** Get the AML_BYTE_ENCODING entry in the AML encoding table + by providing an OpCode/SubOpCode couple. + + @param [in] OpCode OpCode. + @param [in] SubOpCode SubOpCode. + + @return The corresponding AML_BYTE_ENCODING entry. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetByteEncodingByOpCode ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + UINT32 Index; + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0])); + Index++) { + if ((mAmlByteEncoding[Index].OpCode =3D=3D OpCode) && + (mAmlByteEncoding[Index].SubOpCode =3D=3D SubOpCode)) { + return &mAmlByteEncoding[Index]; + } + } + return NULL; +} + +/** Get the AML_BYTE_ENCODING entry in the field encoding table. + + Note: For Pseudo OpCodes this function returns NULL. + + @param [in] Buffer Pointer to a field OpCode. + No SubOpCode is expected. + + @return The corresponding AML_BYTE_ENCODING entry + in the field encoding table. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetFieldEncoding ( + IN CONST UINT8 * Buffer + ) +{ + UINT8 OpCode; + UINT32 Index; + + if (Buffer =3D=3D NULL) { + ASSERT (0); + return NULL; + } + + // Get OpCode. + OpCode =3D *Buffer; + + // Search in the table. + for (Index =3D 0; + Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0])= ); + Index++) { + if (mAmlFieldEncoding[Index].OpCode =3D=3D OpCode) { + if ((mAmlFieldEncoding[Index].Attribute & AML_IS_PSEUDO_OPCODE) =3D= =3D + AML_IS_PSEUDO_OPCODE) { + // A pseudo OpCode cannot be parsed as it is internal to this libr= ary. + // The NamedField encoding can be detected because it begins with a + // char. + ASSERT (0); + return NULL; + } + return &mAmlFieldEncoding[Index]; + } + } + + return NULL; +} + +/** Get the AML_BYTE_ENCODING entry in the field encoding table + by providing an OpCode/SubOpCode couple. + + @param [in] OpCode OpCode. + @param [in] SubOpCode SubOpCode. + + @return The corresponding AML_BYTE_ENCODING entry + in the field encoding table. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetFieldEncodingByOpCode ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + UINT32 Index; + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0])= ); + Index++) { + if ((mAmlFieldEncoding[Index].OpCode =3D=3D OpCode) && + (mAmlFieldEncoding[Index].SubOpCode =3D=3D SubOpCode)) { + return &mAmlFieldEncoding[Index]; + } + } + return NULL; +} + +// Enable this function for debug. +#if !defined (MDEPKG_NDEBUG) +/** Look for an OpCode/SubOpCode couple in the AML grammar, + and return a corresponding string. + + @param [in] OpCode The OpCode. + @param [in] SubOpCode The SubOpCode. + + @return A string describing the OpCode/SubOpCode couple. + NULL if not found. +**/ +CONST +CHAR8 * +AmlGetOpCodeStr ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + EAML_PARSE_INDEX Index; + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0])); + Index++) { + if ((mAmlByteEncoding[Index].OpCode =3D=3D OpCode) && + (mAmlByteEncoding[Index].SubOpCode =3D=3D SubOpCode)) { + return mAmlByteEncoding[Index].Str; + } + } + + ASSERT (0); + return NULL; +} + +/** Look for an OpCode/SubOpCode couple in the AML field element grammar, + and return a corresponding string. + + @param [in] OpCode The OpCode. + @param [in] SubOpCode The SubOpCode. Must be zero. + + @return A string describing the OpCode/SubOpCode couple. + NULL if not found. +**/ +CONST +CHAR8 * +AmlGetFieldOpCodeStr ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + EAML_PARSE_INDEX Index; + + if (SubOpCode !=3D 0) { + ASSERT (0); + return NULL; + } + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0])= ); + Index++) { + if ((mAmlFieldEncoding[Index].OpCode =3D=3D OpCode)) { + return mAmlFieldEncoding[Index].Str; + } + } + + ASSERT (0); + return NULL; +} +#endif // MDEPKG_NDEBUG + +/** Check whether the OpCode/SubOpcode couple is a valid entry + in the AML grammar encoding table. + + @param [in] OpCode OpCode to check. + @param [in] SubOpCode SubOpCode to check. + + @retval TRUE The OpCode/SubOpCode couple is valid. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsOpCodeValid ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + EAML_PARSE_INDEX Index; + + // Search the table. + for (Index =3D 0; + Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0])); + Index++) { + if ((mAmlByteEncoding[Index].OpCode =3D=3D OpCode) && + (mAmlByteEncoding[Index].SubOpCode =3D=3D SubOpCode)) { + return TRUE; + } + } + return FALSE; +} + +/** AML_PARSE_FORMAT to EAML_NODE_DATA_TYPE translation table. + + AML_PARSE_FORMAT describes an internal set of values identifying the typ= es + that can be found while parsing an AML bytestream. + EAML_NODE_DATA_TYPE describes an external set of values allowing to iden= tify + what type of data can be found in data nodes. +*/ +GLOBAL_REMOVE_IF_UNREFERENCED +STATIC +CONST +EAML_NODE_DATA_TYPE mAmlTypeToNodeDataType[] =3D { + EAmlNodeDataTypeNone, // EAmlNone + EAmlNodeDataTypeUInt, // EAmlUInt8 + EAmlNodeDataTypeUInt, // EAmlUInt16 + EAmlNodeDataTypeUInt, // EAmlUInt32 + EAmlNodeDataTypeUInt, // EAmlUInt64 + EAmlNodeDataTypeReserved5, // EAmlObject + EAmlNodeDataTypeNameString, // EAmlName + EAmlNodeDataTypeString, // EAmlString + EAmlNodeDataTypeFieldPkgLen // EAmlFieldPkgLen +}; + +/** Convert an AML_PARSE_FORMAT to its corresponding EAML_NODE_DATA_TYPE. + + @param [in] AmlType Input AML Type. + + @return The corresponding EAML_NODE_DATA_TYPE. + EAmlNodeDataTypeNone if not found. +**/ +EAML_NODE_DATA_TYPE +EFIAPI +AmlTypeToNodeDataType ( + IN AML_PARSE_FORMAT AmlType + ) +{ + if (AmlType >=3D + (sizeof (mAmlTypeToNodeDataType) / sizeof (mAmlTypeToNodeDataType[0]= ))) { + ASSERT (0); + return EAmlNodeDataTypeNone; + } + + return mAmlTypeToNodeDataType[AmlType]; +} + +/** Get the package length from the buffer. + + @param [in] Buffer AML buffer. + @param [out] PkgLength The interpreted PkgLen value. + Length cannot exceed 2^28. + + @return The number of bytes to represent the package length. + 0 if an issue occurred. +**/ +UINT32 +EFIAPI +AmlGetPkgLength ( + IN CONST UINT8 * Buffer, + OUT UINT32 * PkgLength + ) +{ + UINT8 LeadByte; + UINT8 ByteCount; + UINT32 RealLength; + UINT32 Offset; + + if ((Buffer =3D=3D NULL) || + (PkgLength =3D=3D NULL)) { + ASSERT (0); + return 0; + } + + /* From ACPI 6.3 specification, s20.2.4 "Package Length Encoding": + + PkgLength :=3D PkgLeadByte | + | + | + + + PkgLeadByte :=3D + + + + Note: + The high 2 bits of the first byte reveal how many + follow bytes are in the PkgLength. If the + PkgLength has only one byte, bit 0 through 5 are + used to encode the package length (in other + words, values 0-63). If the package length value + is more than 63, more than one byte must be + used for the encoding in which case bit 4 and 5 of + the PkgLeadByte are reserved and must be zero. + If the multiple bytes encoding is used, bits 0-3 of + the PkgLeadByte become the least significant 4 + bits of the resulting package length value. The next + ByteData will become the next least + significant 8 bits of the resulting value and so on, + up to 3 ByteData bytes. Thus, the maximum + package length is 2**28. + */ + + LeadByte =3D *Buffer; + ByteCount =3D (LeadByte >> 6) & 0x03U; + Offset =3D ByteCount + 1U; + RealLength =3D 0; + + // Switch on the number of bytes used to store the PkgLen. + switch (ByteCount) { + case 0: + { + RealLength =3D LeadByte; + break; + } + case 1: + { + RealLength =3D *(Buffer + 1); + RealLength =3D (RealLength << 4) | (LeadByte & 0xF); + break; + } + case 2: + { + RealLength =3D *(Buffer + 1); + RealLength |=3D ((UINT32)(*(Buffer + 2))) << 8; + RealLength =3D (RealLength << 4) | (LeadByte & 0xF); + break; + } + case 3: + { + RealLength =3D *(Buffer + 1); + RealLength |=3D ((UINT32)(*(Buffer + 2))) << 8; + RealLength |=3D ((UINT32)(*(Buffer + 3))) << 16; + RealLength =3D (RealLength << 4) | (LeadByte & 0xF); + break; + } + default: + { + ASSERT (0); + Offset =3D 0; + break; + } + } // switch + + *PkgLength =3D RealLength; + + return Offset; +} + +/** Convert the Length to the AML PkgLen encoding, + then and write it in the Buffer. + + @param [in] Length Length to convert. + Length cannot exceed 2^28. + @param [out] Buffer Write the result in this Buffer. + + @return The number of bytes used to write the Length. +**/ +UINT8 +EFIAPI +AmlSetPkgLength ( + IN UINT32 Length, + OUT UINT8 * Buffer + ) +{ + UINT8 LeadByte; + UINT8 Offset; + UINT8 CurrentOffset; + UINT8 CurrentShift; + UINT32 ComputedLength; + + if (Buffer =3D=3D NULL) { + ASSERT (0); + return 0; + } + + LeadByte =3D 0; + Offset =3D 0; + + if ((Length < (1 << 6))) { + // Length < 2^6, only need one byte to encode it. + LeadByte =3D (UINT8)Length; + + } else { + // Need more than one byte to encode it. + // Test Length to find how many bytes are needed. + + if (Length >=3D (1 << 28)) { + // Length >=3D 2^28, should not be possible. + ASSERT (0); + return 0; + + } else if (Length >=3D (1 << 20)) { + // Length >=3D 2^20 + Offset =3D 3; + + } else if (Length >=3D (1 << 12)) { + // Length >=3D 2^12 + Offset =3D 2; + + } else if (Length >=3D (1 << 6)) { + // Length >=3D 2^6 + Offset =3D 1; + + } else { + // Should not be possible. + ASSERT (0); + return 0; + } + + // Set the LeadByte. + LeadByte =3D (UINT8)(Offset << 6); + LeadByte =3D (UINT8)(LeadByte | (Length & 0xF)); + } + + // Write to the Buffer. + *Buffer =3D LeadByte; + CurrentOffset =3D 1; + while (CurrentOffset < (Offset + 1)) { + CurrentShift =3D (UINT8)((CurrentOffset - 1) * 8); + ComputedLength =3D Length & (UINT32)(0x00000FF0 << CurrentShift); + ComputedLength =3D (ComputedLength) >> (4 + CurrentShift); + LeadByte =3D (UINT8)(ComputedLength & 0xFF); + *(Buffer + CurrentOffset) =3D LeadByte; + CurrentOffset++; + } + + return ++Offset; +} + +/** Compute the number of bytes required to write a package length. + + @param [in] Length The length to convert in the AML package length + encoding style. + Length cannot exceed 2^28. + + @return The number of bytes required to write the Length. +**/ +UINT8 +EFIAPI +AmlComputePkgLengthWidth ( + IN UINT32 Length + ) +{ + // Length >=3D 2^28, should not be possible. + if (Length >=3D (1 << 28)) { + ASSERT (0); + return 0; + + } else if (Length >=3D (1 << 20)) { + // Length >=3D 2^20 + return 4; + + } else if (Length >=3D (1 << 12)) { + // Length >=3D 2^12 + return 3; + + } else if (Length >=3D (1 << 6)) { + // Length >=3D 2^6 + return 2; + } + + // Length < 2^6 + return 1; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h b/Dyn= amicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h new file mode 100644 index 0000000000000000000000000000000000000000..ba1228621303f5208f94891d465= 94c50637195db --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h @@ -0,0 +1,330 @@ +/** @file + AML grammar definitions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_H_ +#define AML_H_ + +#include +#include +#include + +#if !defined (MDEPKG_NDEBUG) +#define AML_DEBUG_STR(str) str, +#else +#define AML_DEBUG_STR(x) +#endif // MDEPKG_NDEBUG + +/** AML types. + + In the AML bytestream, data is represented using one of the following ty= pes. + These types are used in the parsing logic to know what kind of data is + expected next in the bytestream. This allows to parse data according + to the AML_PARSE_FORMAT type. + E.g.: A string will not be parsed in the same way as a UINT8. + + These are internal types. +*/ +typedef enum EAmlParseFormat { + EAmlNone =3D 0, ///< No data expected. + EAmlUInt8, ///< One byte value evaluated as a UINT8. + EAmlUInt16, ///< Two byte value evaluated as a UINT16. + EAmlUInt32, ///< Four byte value evaluated as a UINT32. + EAmlUInt64, ///< Eight byte value evaluated as a UINT64. + EAmlObject, ///< AML object, starting with an OpCode/SubOpCode + /// couple, potentially followed by package length. + /// EAmlName is a subtype of an EAmlObject. + /// Indeed, an EAmlName can also be evaluated as + /// an EAmlObject in the parsing. + EAmlName, ///< Name corresponding to the NameString keyword + /// in the ACPI specification. E.g.: "\_SB_.DEV0" + EAmlString, ///< NULL terminated string. + EAmlFieldPkgLen, ///< A field package length (PkgLen). A data node of= this + /// type can only be found in a field list, in a + /// NamedField statement. The PkgLen is otherwise + /// part of the object node structure. + EAmlParseFormatMax ///< Max enum. +} AML_PARSE_FORMAT; + +/** AML attributes + + To add some more information to the byte encoding, it is possible to add + these attributes. +*/ +typedef UINT32 AML_OP_ATTRIBUTE; + +/** A PkgLength is expected between the OpCode/SubOpCode couple and the fi= rst + fixed argument of the object. +*/ +#define AML_HAS_PKG_LENGTH 0x00001U + +/** The object's OpCode is actually a character. Encodings with this attri= bute + don't describe objects. The dual/multi name prefix have this attribute, + indicating the start of a longer NameString. +*/ +#define AML_IS_NAME_CHAR 0x00002U + +/** A variable list of arguments is following the last fixed argument. Each + argument is evaluated as an EAmlObject. +*/ +#define AML_HAS_CHILD_OBJ 0x00004U + +/** This is a sub-type of a variable list of arguments. It can only be + found in buffer objects. A ByteList is either a list of + bytes or a list of resource data elements. Resource data elements + have specific opcodes. +*/ +#define AML_HAS_BYTE_LIST 0x00008U + +/** This is a sub-type of a variable list of arguments. It can only be + found in Fields, IndexFields and BankFields. + A FieldList is made of FieldElements. FieldElements have specific opco= des. +*/ +#define AML_HAS_FIELD_LIST 0x00010U + +/** This object node is a field element. Its opcode is to be fetched from + the field encoding table. +*/ +#define AML_IS_FIELD_ELEMENT 0x00020U + +/** The object has a name and which is part of the AML namespace. The name + can be found in the fixed argument list at the NameIndex. +*/ +#define AML_IN_NAMESPACE 0x10000U + +/** Some OpCodes have been created in this library. They are called + pseudo opcodes and must stay internal to this library. +*/ +#define AML_IS_PSEUDO_OPCODE 0x20000U + +/** Encoding of an AML object. + + Every AML object has a specific encoding. This encoding information + is used to parse AML objects. A table of AML_BYTE_ENCODING entries + allows to parse an AML bytestream. + This structure is also used to describe field objects. + + Cf. ACPI 6.3 specification, s20.2. +*/ +typedef struct _AML_BYTE_ENCODING { +// Enable this field for debug. +#if !defined (MDEPKG_NDEBUG) + /// String field allowing to print the AML object. + CONST CHAR8 * Str; +#endif // MDEPKG_NDEBUG + + /// OpCode of the AML object. + UINT8 OpCode; + + /// SubOpCode of the AML object. + /// The SubOpcode field has a valid value when the OpCode is 0x5B, + /// otherwise this field must be zero. + /// For field objects, the SubOpCode is not used. + UINT8 SubOpCode; + + /// Number of fixed arguments for the AML statement represented + /// by the OpCode & SubOpcode. + /// Maximum is 6 for AML objects. + /// Maximum is 3 for field objects. + EAML_PARSE_INDEX MaxIndex; + + /// If the encoding has the AML_IN_NAMESPACE attribute (cf Attribute + /// field below), indicate where to find the name in the fixed list + /// of arguments. + EAML_PARSE_INDEX NameIndex; + + /// Type of each fixed argument. + AML_PARSE_FORMAT Format[EAmlParseIndexMax]; + + /// Additional information on the AML object. + AML_OP_ATTRIBUTE Attribute; +} AML_BYTE_ENCODING; + +/** Get the AML_BYTE_ENCODING entry in the AML encoding table. + + Note: For Pseudo OpCodes this function returns NULL. + + @param [in] Buffer Pointer to an OpCode/SubOpCode couple. + If *Buffer =3D 0x5b (extended OpCode), + Buffer must be at least two bytes long. + + @return The corresponding AML_BYTE_ENCODING entry. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetByteEncoding ( + IN CONST UINT8 * Buffer + ); + +/** Get the AML_BYTE_ENCODING entry in the AML encoding table + by providing an OpCode/SubOpCode couple. + + @param [in] OpCode OpCode. + @param [in] SubOpCode SubOpCode. + + @return The corresponding AML_BYTE_ENCODING entry. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetByteEncodingByOpCode ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +/** Get the AML_BYTE_ENCODING entry in the field encoding table. + + Note: For Pseudo OpCodes this function returns NULL. + + @param [in] Buffer Pointer to a field OpCode. + No SubOpCode is expected. + + @return The corresponding AML_BYTE_ENCODING entry + in the field encoding table. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetFieldEncoding ( + IN CONST UINT8 * Buffer + ); + +/** Get the AML_BYTE_ENCODING entry in the field encoding table + by providing an OpCode/SubOpCode couple. + + @param [in] OpCode OpCode. + @param [in] SubOpCode SubOpCode. + + @return The corresponding AML_BYTE_ENCODING entry + in the field encoding table. + NULL if not found. +**/ +CONST +AML_BYTE_ENCODING * +EFIAPI +AmlGetFieldEncodingByOpCode ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +// Enable this function for debug. +#if !defined (MDEPKG_NDEBUG) +/** Look for an OpCode/SubOpCode couple in the AML grammar, + and return a corresponding string. + + @param [in] OpCode The OpCode. + @param [in] SubOpCode The SubOpCode. + + @return A string describing the OpCode/SubOpCode couple. + NULL if not found. +**/ +CONST +CHAR8 * +AmlGetOpCodeStr ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +/** Look for an OpCode/SubOpCode couple in the AML field element grammar, + and return a corresponding string. + + @param [in] OpCode The OpCode. + @param [in] SubOpCode The SubOpCode. Must be zero. + + @return A string describing the OpCode/SubOpCode couple. + NULL if not found. +**/ +CONST +CHAR8 * +AmlGetFieldOpCodeStr ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); +#endif // MDEPKG_NDEBUG + +/** Check whether the OpCode/SubOpcode couple is a valid entry + in the AML grammar encoding table. + + @param [in] OpCode OpCode to check. + @param [in] SubOpCode SubOpCode to check. + + @retval TRUE The OpCode/SubOpCode couple is valid. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsOpCodeValid ( + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +/** Convert an AML_PARSE_FORMAT to its corresponding EAML_NODE_DATA_TYPE. + + @param [in] AmlType Input AML Type. + + @return The corresponding EAML_NODE_DATA_TYPE. + EAmlNodeDataTypeNone if not found. +**/ +EAML_NODE_DATA_TYPE +EFIAPI +AmlTypeToNodeDataType ( + IN AML_PARSE_FORMAT AmlType + ); + +/** Get the package length from the buffer. + + @param [in] Buffer AML buffer. + @param [out] PkgLength The interpreted PkgLen value. + Length cannot exceed 2^28. + + @return The number of bytes to represent the package length. + 0 if an issue occurred. +**/ +UINT32 +EFIAPI +AmlGetPkgLength ( + IN CONST UINT8 * Buffer, + OUT UINT32 * PkgLength + ); + +/** Convert the Length to the AML PkgLen encoding, + then and write it in the Buffer. + + @param [in] Length Length to convert. + Length cannot exceed 2^28. + @param [out] Buffer Write the result in this Buffer. + + @return The number of bytes used to write the Length. +**/ +UINT8 +EFIAPI +AmlSetPkgLength ( + IN UINT32 Length, + OUT UINT8 * Buffer + ); + +/** Compute the number of bytes required to write a package length. + + @param [in] Length The length to convert in the AML package length + encoding style. + Length cannot exceed 2^28. + + @return The number of bytes required to write the Length. +**/ +UINT8 +EFIAPI +AmlComputePkgLengthWidth ( + IN UINT32 Length + ); + +#endif // AML_H_ + --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64081): https://edk2.groups.io/g/devel/message/64081 Mute This Topic: https://groups.io/mt/76149137/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64082+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245797410753.0898463317172; Wed, 12 Aug 2020 08:23:17 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id PnFiYY1788612xKmWHX7suGO; Wed, 12 Aug 2020 08:23:14 -0700 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com (EUR05-VI1-obe.outbound.protection.outlook.com [40.107.21.77]) by mx.groups.io with SMTP id smtpd.web12.16966.1597245792439210740 for ; Wed, 12 Aug 2020 08:23:13 -0700 X-Received: from AM6P195CA0099.EURP195.PROD.OUTLOOK.COM (2603:10a6:209:86::40) by HE1PR0802MB2426.eurprd08.prod.outlook.com (2603:10a6:3:e1::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:08 +0000 X-Received: from VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:86:cafe::ad) by AM6P195CA0099.outlook.office365.com (2603:10a6:209:86::40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:08 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64082+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT005.mail.protection.outlook.com (10.152.18.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:08 +0000 X-Received: ("Tessian outbound 7a6fb63c1e64:v64"); Wed, 12 Aug 2020 15:23:08 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: c583ff2ae84a63c6 X-CR-MTA-TID: 64aa7808 X-Received: from e805a9d0093e.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 26B992BF-E1A5-4DE0-A229-3354111565FD.1; Wed, 12 Aug 2020 15:23:02 +0000 X-Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id e805a9d0093e.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:02 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d8cXsxwdjMEYEroTCQVw5c3ccGxGZrHfkPVpDzM2xqj4Xvla+ZR0E8bsX54Y+MxIBslj6acAl9+34/ErRRpyJWOzbdkyKvqj56SDgUqcdwMThPJzx/muiLt3e45fpIfg2bYnZmvh0ai8EbfzQUHpOZA5QVmkrFWoaEs7aYz0PiP7wjy4sfkNHem84ZHQIa+uGHE6YJ3TW9Ig5OcC/9qiqlSJzWXcFAhgccgk/CTLiuVgM2rrRdTDLUcxhcBKB9LLAs8asKxZff4aepVFYBL5eKMsIQQ9TcaGqXqzhVzQF4+kGOhcniSwnRPauCsqu4N7RnzZ1yiIcde3uLfzyb+yCw== 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-SenderADCheck; bh=UPnzeZU3h57aQAh7WpqlaTv7cL3WAaETHFbul1ns8ew=; b=nPGnKrrvuVCDHNeC79ILSWzBfo1QZruCs24NOGpkTuS2ZKG0zALIfWcYCIcNYut0iFwMZbOHMj9XEOUPRoc/hqk+dFm2tszL+04m92zMgVPtr0oMjaHg1XZrP/BSpoeIOnCQG3W5uITRgRIuYjqf+We4i/pvBlJ9hnmyO/qcsOxoYcve2D7TEbovbN8HScioGdN6IXXMd/BYWhxKp26iWgelvcEi2DDgV/1XxqD73Lpq055X8OYFy9AY28chBMinEKG2a5xz2q8t9TCYT/dCOZYoycLglynwb+toTWOOfymUVTGj7WK+jXPHsqP0Sbukr1QQE7SorAZUKpHN/gP1jQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR0301CA0057.eurprd03.prod.outlook.com (2603:10a6:4:54::25) by DB6PR0802MB2294.eurprd08.prod.outlook.com (2603:10a6:4:85::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:22:59 +0000 X-Received: from DB5EUR03FT060.eop-EUR03.prod.protection.outlook.com (2603:10a6:4:54:cafe::50) by DB6PR0301CA0057.outlook.office365.com (2603:10a6:4:54::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:22:59 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT060.mail.protection.outlook.com (10.152.21.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:22:59 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:22:48 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:22:47 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 04/30] DynamicTablesPkg: AML node definitions Date: Wed, 12 Aug 2020 16:22:10 +0100 Message-ID: <20200812152236.31164-5-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 29709bb0-17d4-4784-41c1-08d83ed39e19 X-MS-TrafficTypeDiagnostic: DB6PR0802MB2294:|HE1PR0802MB2426: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2150;OLM:2150; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: 2VaEO7Inqgapi92+Wujyp0afL3/88Bb5fYr7xKFDev89e6IZ820hzXGAGFzlUKj9XOZFSGPna4xy4mTXM7ZOeLtjPXtZ3KjqHAPJQm3tTH2po1vlCq2AYu1UgDLoDqM1ueEiXUOhJ66ao60p6koo3iAfXHNnthwP8SnQoZ03xMmW5BC+YlxKU7UlRym9VGzobNfE/x9KVkIlnBBE3YxEdjrG/EDEch17DItxusk4hD8LFp0W4kdmT3Fr2svDm4Y9Lfk3dLFgrKdtKWSKhfzDlSpUh/5t3aafu8PgbFFuZlJwFj9qEnRU9IrfgDNJKvNYyM6cQ1uvVfQbkfVAHZcpjxthuGtp3MuDHIoC1u8V97v13UTzwIToXch8QHvTjPt6MfszalnViSjM/zvp2WOZfw== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(346002)(376002)(136003)(396003)(39860400002)(46966005)(8676002)(8936002)(5660300002)(70206006)(26005)(19627235002)(54906003)(316002)(478600001)(2906002)(6666004)(70586007)(83380400001)(6916009)(47076004)(82740400003)(36756003)(336012)(426003)(82310400002)(81166007)(356005)(2616005)(1076003)(44832011)(86362001)(186003)(7696005)(4326008)(30864003)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0802MB2294 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 76181e82-16bc-4612-7209-08d83ed39896 X-Microsoft-Antispam-Message-Info: enz9jfjN4dQJ85Pq6DFqWJrC1dXnhDCGwznesdns/tWImQCBQ89Lwdwkhdi9kfyPhNYAi3Y20RpgLvYqZn5mhJQIXBwRYi0z8FcxNF5wCtxEkxGDloojvWwOrhWzz3nFcETqkiaiVNsYleq5g+xJCXMwlZ4Ykg5gW+yf1B9rkLmUblvWTwFYjigm0ojTquliVMFw+qy8TiLS6MXhnvtOZC6w2OozPF3xAC8LfI1JcESlb3ECbTAi36LpBzK+E1Xiss8G/Teqy9JyQBQxQqLP/QBECA5J3ma2JTMC2eoA/aJm+GITdEyY87XGegPlBOC8SQKPa1K3snw17PDl7B0mtw5w6v1AfvB0gkO1tUnBl3LR2wCLe/qIMQ7crLLreiBjMwH2oj3AsbGRqavzBS6iJg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:08.3284 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 29709bb0-17d4-4784-41c1-08d83ed39e19 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: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0802MB2426 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 4mkWN3ieXPxjjT2MO6B9IqKqx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245794; bh=X4Vk9UQUeA+g9bIuMcezJe75ex9KeAkHwIgOD3cWLpg=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=udy0/wVRPL80MPR1qGYIgLfBvk2kLzywYUWa39xbvWH8DCn3rSQ9ztYR0DxrRPt+RqL y1ttpxxOK5MOEYPXO8UpTpP8i7rj/hQBSHA9AM6g3js23tnuUTpybtY419fkNcoK7Bq7c GuGtm1iPHOP9Q86MofMz7SmMrUpTZ7hLt3M= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML has a complex grammar, and this makes runtime modifications on an AML byte stream difficult. A solution is to parse the AML bytecode and represent it in a tree data structure, henceforth called the AML tree. The AML tree is composite in the sense it has the following node types: - A 'Root node' that represents the root of the AML tree. - An 'Object node' that contains the OP Code (AML Encoding). - A 'Data node' that contains a data buffer. The Root node contains the Definition block header (ACPI header) and a Variable Argument list. The Object node is composed of an array of Fixed Arguments and a Variable Argument list. Fixed arguments can be either Object Nodes or Data nodes. Their placement (index) in the Fixed Argument array is defined by the AML encoding of the enclosing Object Node. Variable arguments can be Object nodes or Data nodes. Following is a depiction of a typical AML tree: (/) # Root Node \ |-{(N1)->...} # Variable Argument list, N1 is \ # an Object Node \ /-i # Child of fixed argument b \ / |- [a][b][c][d] # Fixed Arguments |- {(e)->(f)->(g)} # Variable Arguments \ \-h # Child of variable argument e Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h | 183 ++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c | 673 +++++= +++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h | 212 ++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c | 566 +++++= +++++++++++ 4 files changed, 1634 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h b/Dyna= micTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h new file mode 100644 index 0000000000000000000000000000000000000000..fffba6d54b64e8f37ca33d99465= ec22eb81b5a99 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h @@ -0,0 +1,183 @@ +/** @file + AML Node Definition. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_NODE_DEFINES_H_ +#define AML_NODE_DEFINES_H_ + +#include +#include + +/** AML header node. + + This abstract class represents either a root/object/data node. + All the enumerated nodes have this same common header. +*/ +typedef struct AmlNodeHeader { + /// This must be the first field in this structure. + LIST_ENTRY Link; + + /// Parent of this node. NULL for the root node. + struct AmlNodeHeader * Parent; + + /// Node type allowing to identify a root/object/data node. + EAML_NODE_TYPE NodeType; +} AML_NODE_HEADER; + +/** Node handle. +*/ +typedef AML_NODE_HEADER* AML_NODE_HANDLE; + +/** AML root node. + + The root node is unique and at the head of of tree. It is a fake node us= ed + to maintain the list of AML statements (stored as object nodes) which are + at the first scope level. +*/ +typedef struct AmlRootNode { + /// Header information. Must be the first field of the struct. + AML_NODE_HEADER NodeHeader; + + /// List of object nodes being at the first scope level. + /// These are children and can only be object nodes. + LIST_ENTRY VariableArgs; + + /// ACPI DSDT/SSDT header. + EFI_ACPI_DESCRIPTION_HEADER * SdtHeader; +} AML_ROOT_NODE; + +/** Root Node handle. +*/ +typedef AML_ROOT_NODE* AML_ROOT_NODE_HANDLE; + +/** AML object node. + + Object nodes match AML statements. They are associated with an + OpCode/SubOpCode, and can have children. +*/ +typedef struct AmlObjectNode { + /// Header information. Must be the first field of the struct. + AML_NODE_HEADER NodeHeader; + + /// Some object nodes have a variable list of arguments. + /// These are children and can only be object/data nodes. + /// Cf ACPI specification, s20.3. + LIST_ENTRY VariableArgs; + + /// Fixed arguments of this object node. + /// These are children and can be object/data nodes. + /// Cf ACPI specification, s20.3. + AML_NODE_HEADER * FixedArgs[EAmlParseIndexMax]; + + /// AML byte encoding. Stores the encoding information: + /// (OpCode/SubOpCode/number of fixed arguments/ attributes). + CONST AML_BYTE_ENCODING * AmlByteEncoding; + + /// Some nodes have a PkgLen following their OpCode/SubOpCode in the + /// AML bytestream. This field stores the decoded value of the PkgLen. + UINT32 PkgLen; +} AML_OBJECT_NODE; + +/** Object Node handle. +*/ +typedef AML_OBJECT_NODE* AML_OBJECT_NODE_HANDLE; + +/** AML data node. + + Data nodes store the smallest pieces of information. + E.g.: UINT8, UINT64, NULL terminated string, etc. + Data node don't have children nodes. +*/ +typedef struct AmlDataNode { + /// Header information. Must be the first field of the struct. + AML_NODE_HEADER NodeHeader; + + /// Tag identifying what data is stored in this node. + /// E.g. UINT, NULL terminated string, resource data element, etc. + EAML_NODE_DATA_TYPE DataType; + + /// Buffer containing the data stored by this node. + UINT8 * Buffer; + + /// Size of the Buffer. + UINT32 Size; +} AML_DATA_NODE; + +/** Data Node handle. +*/ +typedef AML_DATA_NODE* AML_DATA_NODE_HANDLE; + +/** Check whether a Node has a valid NodeType. + + @param [in] Node The node to check. + + @retval TRUE The Node has a valid NodeType. + @retval FALSE Otherwise. +*/ +#define IS_AML_NODE_VALID(Node) = \ + ((Node !=3D NULL) = && \ + ((((CONST AML_NODE_HEADER*)Node)->NodeType > EAmlNodeUnknown) = || \ + (((CONST AML_NODE_HEADER*)Node)->NodeType < EAmlNodeMax))) + +/** Check whether a Node is a root node. + + @param [in] Node The node to check. + + @retval TRUE The Node is a root node. + @retval FALSE Otherwise. +*/ +#define IS_AML_ROOT_NODE(Node) = \ + ((Node !=3D NULL) = && \ + (((CONST AML_NODE_HEADER*)Node)->NodeType =3D=3D EAmlNodeRoot)) + +/** Check whether a Node is an object node. + + @param [in] Node The node to check. + + @retval TRUE The Node is an object node. + @retval FALSE Otherwise. +*/ +#define IS_AML_OBJECT_NODE(Node) = \ + ((Node !=3D NULL) = && \ + (((CONST AML_NODE_HEADER*)Node)->NodeType =3D=3D EAmlNodeObject= )) + +/** Check whether a Node is a data node. + + @param [in] Node The node to check. + + @retval TRUE The Node is a data node. + @retval FALSE Otherwise. +*/ +#define IS_AML_DATA_NODE(Node) = \ + ((Node !=3D NULL) = && \ + (((CONST AML_NODE_HEADER*)Node)->NodeType =3D=3D EAmlNodeData)) + +/** Check whether a Node has a parent. + + @param [in] Node The node to check. + + @retval TRUE The Node is a data node. + @retval FALSE Otherwise. +*/ +#define AML_NODE_HAS_PARENT(Node) = \ + (IS_AML_NODE_VALID (Node) = && \ + (((CONST AML_NODE_HEADER*)Node)->Parent !=3D NULL)) + +/** Check that the Node is not attached somewhere. + This doesn't mean the node cannot have children. + + @param [in] Node The node to check. + + @retval TRUE The Node has been detached. + @retval FALSE Otherwise. +*/ +#define AML_NODE_IS_DETACHED(Node) = \ + (IS_AML_NODE_VALID (Node) = && \ + IsListEmpty ((CONST LIST_ENTRY*)Node) = && \ + (((CONST AML_NODE_HEADER*)Node)->Parent =3D=3D NULL)) + +#endif // AML_NODE_DEFINES_H_ diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c b/Dynami= cTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c new file mode 100644 index 0000000000000000000000000000000000000000..2c80440a447ad261290a2cf84a8= edd3434cf9e5e --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c @@ -0,0 +1,673 @@ +/** @file + AML Node. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include + +/** Initialize an AML_NODE_HEADER structure. + + @param [in] Node Pointer to a node header. + @param [in] NodeType NodeType to initialize the Node with. + Must be an EAML_NODE_TYPE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlInitializeNodeHeader ( + IN AML_NODE_HEADER * Node, + IN EAML_NODE_TYPE NodeType + ) +{ + if (Node =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + InitializeListHead (&Node->Link); + + Node->Parent =3D NULL; + Node->NodeType =3D NodeType; + + return EFI_SUCCESS; +} + +/** Delete a root node and its ACPI DSDT/SSDT header. + + It is the caller's responsibility to check the RootNode has been removed + from the tree and is not referencing any other node in the tree. + + @param [in] RootNode Pointer to a root node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlDeleteRootNode ( + IN AML_ROOT_NODE * RootNode + ) +{ + if (!IS_AML_ROOT_NODE (RootNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if ((RootNode->SdtHeader !=3D NULL)) { + FreePool (RootNode->SdtHeader); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (RootNode); + return EFI_SUCCESS; +} + +/** Create an AML_ROOT_NODE. + This node will be the root of the tree. + + @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT header to copy + the data from. + @param [out] NewRootNodePtr The created AML_ROOT_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateRootNode ( + IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader, + OUT AML_ROOT_NODE ** NewRootNodePtr + ) +{ + EFI_STATUS Status; + AML_ROOT_NODE * RootNode; + + if ((SdtHeader =3D=3D NULL) || + (NewRootNodePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + RootNode =3D AllocateZeroPool (sizeof (AML_ROOT_NODE)); + if (RootNode =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlInitializeNodeHeader (&RootNode->NodeHeader, EAmlNodeRoot); + if (EFI_ERROR (Status)) { + FreePool (RootNode); + ASSERT (0); + return Status; + } + + InitializeListHead (&RootNode->VariableArgs); + + RootNode->SdtHeader =3D AllocateCopyPool ( + sizeof (EFI_ACPI_DESCRIPTION_HEADER), + SdtHeader + ); + if (RootNode->SdtHeader =3D=3D NULL) { + ASSERT (0); + AmlDeleteRootNode (RootNode); + return EFI_OUT_OF_RESOURCES; + } + + *NewRootNodePtr =3D RootNode; + + return EFI_SUCCESS; +} + +/** Delete an object node. + + It is the caller's responsibility to check the ObjectNode has been remov= ed + from the tree and is not referencing any other node in the tree. + + @param [in] ObjectNode Pointer to an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlDeleteObjectNode ( + IN AML_OBJECT_NODE * ObjectNode + ) +{ + if (!IS_AML_OBJECT_NODE (ObjectNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (ObjectNode); + return EFI_SUCCESS; +} + +/** Create an AML_OBJECT_NODE. + + @param [in] AmlByteEncoding Byte encoding entry. + @param [in] PkgLength PkgLength of the node if the AmlByteEnco= ding + has the PkgLen attribute. + 0 otherwise. + @param [out] NewObjectNodePtr The created AML_OBJECT_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateObjectNode ( + IN CONST AML_BYTE_ENCODING * AmlByteEncoding, + IN UINT32 PkgLength, + OUT AML_OBJECT_NODE ** NewObjectNodePtr + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + + if ((AmlByteEncoding =3D=3D NULL) || + (NewObjectNodePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ObjectNode =3D AllocateZeroPool (sizeof (AML_OBJECT_NODE)); + if (ObjectNode =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlInitializeNodeHeader (&ObjectNode->NodeHeader, EAmlNodeObj= ect); + if (EFI_ERROR (Status)) { + FreePool (ObjectNode); + ASSERT (0); + return Status; + } + + InitializeListHead (&ObjectNode->VariableArgs); + + // ObjectNode->FixedArgs[...] is already initialised to NULL as the + // ObjectNode is Zero allocated. + ObjectNode->AmlByteEncoding =3D AmlByteEncoding; + ObjectNode->PkgLen =3D PkgLength; + + *NewObjectNodePtr =3D ObjectNode; + + return EFI_SUCCESS; +} + +/** Delete a data node and its buffer. + + It is the caller's responsibility to check the DataNode has been removed + from the tree and is not referencing any other node in the tree. + + @param [in] DataNode Pointer to a data node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlDeleteDataNode ( + IN AML_DATA_NODE * DataNode + ) +{ + if (!IS_AML_DATA_NODE (DataNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (DataNode->Buffer !=3D NULL) { + FreePool (DataNode->Buffer); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (DataNode); + return EFI_SUCCESS; +} + +/** Create an AML_DATA_NODE. + + @param [in] DataType DataType of the node. + @param [in] Data Pointer to the AML bytecode corresponding = to + this node. Data is copied from there. + @param [in] DataSize Number of bytes to consider at the address + pointed by Data. + @param [out] NewDataNodePtr The created AML_DATA_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateDataNode ( + IN EAML_NODE_DATA_TYPE DataType, + IN CONST UINT8 * Data, + IN UINT32 DataSize, + OUT AML_DATA_NODE ** NewDataNodePtr + ) +{ + EFI_STATUS Status; + AML_DATA_NODE * DataNode; + + // A data node must not be created for certain data types. + if ((DataType =3D=3D EAmlNodeDataTypeNone) || + (DataType =3D=3D EAmlNodeDataTypeReserved1) || + (DataType =3D=3D EAmlNodeDataTypeReserved2) || + (DataType =3D=3D EAmlNodeDataTypeReserved3) || + (DataType =3D=3D EAmlNodeDataTypeReserved4) || + (DataType =3D=3D EAmlNodeDataTypeReserved5) || + (Data =3D=3D NULL) || + (DataSize =3D=3D 0) || + (NewDataNodePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + DataNode =3D AllocateZeroPool (sizeof (AML_DATA_NODE)); + if (DataNode =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlInitializeNodeHeader (&DataNode->NodeHeader, EAmlNodeData); + if (EFI_ERROR (Status)) { + FreePool (DataNode); + ASSERT (0); + return Status; + } + + DataNode->Buffer =3D AllocateCopyPool (DataSize, Data); + if (DataNode->Buffer =3D=3D NULL) { + AmlDeleteDataNode (DataNode); + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + DataNode->DataType =3D DataType; + DataNode->Size =3D DataSize; + + *NewDataNodePtr =3D DataNode; + + return EFI_SUCCESS; +} + +/** Delete a Node. + + @param [in] Node Pointer to a Node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteNode ( + IN AML_NODE_HEADER * Node + ) +{ + EFI_STATUS Status; + EAML_PARSE_INDEX Index; + + // Check that the node being deleted is unlinked. + // When removing the node, its parent and list are reset + // with InitializeListHead. Thus it must be empty. + if (!IS_AML_NODE_VALID (Node) || + !AML_NODE_IS_DETACHED (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + switch (Node->NodeType) { + case EAmlNodeRoot: + { + // Check the variable list of arguments has been cleaned. + if (!IsListEmpty (AmlNodeGetVariableArgList (Node))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlDeleteRootNode ((AML_ROOT_NODE*)Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + break; + } + + case EAmlNodeObject: + { + // Check the variable list of arguments has been cleaned. + if (!IsListEmpty (AmlNodeGetVariableArgList (Node))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check the fixed argument list has been cleaned. + for (Index =3D EAmlParseIndexTerm0; Index < EAmlParseIndexMax; Index= ++) { + if (((AML_OBJECT_NODE*)Node)->FixedArgs[Index] !=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + Status =3D AmlDeleteObjectNode ((AML_OBJECT_NODE*)Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + break; + } + + case EAmlNodeData: + { + Status =3D AmlDeleteDataNode ((AML_DATA_NODE*)Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + break; + } + + default: + { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + break; + } + } // switch + + return Status; +} + +/** Check whether ObjectNode has the input attribute. + This function can be used to check ObjectNode is an object node + at the same time. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Attribute Attribute to check for. + + @retval TRUE The node is an AML object and the attribute is present. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasAttribute ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN AML_OP_ATTRIBUTE Attribute + ) +{ + if (!IS_AML_OBJECT_NODE (ObjectNode) || + (ObjectNode->AmlByteEncoding =3D=3D NULL)) { + return FALSE; + } + + return ((ObjectNode->AmlByteEncoding->Attribute & + Attribute) =3D=3D 0 ? FALSE : TRUE); +} + +/** Check whether ObjectNode has the input OpCode/SubOpcode couple. + + @param [in] ObjectNode Pointer to an object node. + @param [in] OpCode OpCode to check + @param [in] SubOpCode SubOpCode to check + + @retval TRUE The node is an AML object and + the Opcode and the SubOpCode match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeCompareOpCode ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + if (!IS_AML_OBJECT_NODE (ObjectNode) || + (ObjectNode->AmlByteEncoding =3D=3D NULL)) { + return FALSE; + } + + ASSERT (AmlIsOpCodeValid (OpCode, SubOpCode)); + + return ((ObjectNode->AmlByteEncoding->OpCode =3D=3D OpCode) && + (ObjectNode->AmlByteEncoding->SubOpCode =3D=3D SubOpCode)) ? + TRUE : FALSE; +} + +/** Check whether a Node is an integer node. + + By integer node we mean an object node having one of the following opcod= e: + - AML_BYTE_PREFIX; + - AML_WORD_PREFIX; + - AML_DWORD_PREFIX; + - AML_QWORD_PREFIX. + + @param [in] Node The node to check. + + @retval TRUE The Node is an integer node. + @retval FALSE Otherwise. +*/ +BOOLEAN +EFIAPI +IsIntegerNode ( + IN AML_OBJECT_NODE * Node + ) +{ + UINT8 OpCode; + + if (!IS_AML_OBJECT_NODE (Node) || + (Node->AmlByteEncoding =3D=3D NULL)) { + return FALSE; + } + + // Check Node is an integer node. + OpCode =3D Node->AmlByteEncoding->OpCode; + if ((OpCode !=3D AML_BYTE_PREFIX) && + (OpCode !=3D AML_WORD_PREFIX) && + (OpCode !=3D AML_DWORD_PREFIX) && + (OpCode !=3D AML_QWORD_PREFIX)) { + return FALSE; + } + + return TRUE; +} + +/** Check whether a Node is a ZeroOp, a OneOp or a OnesOp. + + These two objects don't have a data node holding + a value. This require special handling. + + @param [in] Node The node to check. + + @retval TRUE The Node is a ZeroOp or OneOp. + @retval FALSE Otherwise. +*/ +BOOLEAN +EFIAPI +IsSpecialIntegerNode ( + IN AML_OBJECT_NODE * Node + ) +{ + UINT8 OpCode; + + if (!IS_AML_OBJECT_NODE (Node) || + (Node->AmlByteEncoding =3D=3D NULL)) { + return FALSE; + } + + OpCode =3D Node->AmlByteEncoding->OpCode; + + if ((OpCode !=3D AML_ZERO_OP) && + (OpCode !=3D AML_ONE_OP) && + (OpCode !=3D AML_ONES_OP)) { + return FALSE; + } + + return TRUE; +} + +/** Check whether Node corresponds to a method definition. + + A method definition can be introduced: + - By a method object, having an AML_METHOD_OP OpCode; + - By an external definition of a method, having an AML_EXTERNAL_OP OpCo= de + and an ObjectType byte set to the MethodObj. + + Note: + An alias node, having an AML_ALIAS_OP, can be resolved to a method + definition. This function doesn't handle this case. + + @param [in] Node Node to check whether it is a method definition. + + @retval TRUE The Node is a method definition. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsMethodDefinitionNode ( + IN CONST AML_OBJECT_NODE * Node + ) +{ + AML_DATA_NODE * ObjectType; + + // Node is checked to be an object node aswell. + if (AmlNodeCompareOpCode (Node, AML_METHOD_OP, 0)) { + return TRUE; + } else if (AmlNodeCompareOpCode (Node, AML_EXTERNAL_OP, 0)) { + // If the node is an external definition, check this is a method. + // DefExternal :=3D ExternalOp NameString ObjectType ArgumentCount + // ExternalOp :=3D 0x15 + // ObjectType :=3D ByteData + // ArgumentCount :=3D ByteData (0 =E2=80=93 7) + ObjectType =3D (AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + EAmlParseIndexTerm1 + ); + if (IS_AML_DATA_NODE (ObjectType) && + (ObjectType->DataType =3D=3D EAmlNodeDataTypeUInt) && + ((ObjectType->Size =3D=3D 1))) { + if (*((UINT8*)ObjectType->Buffer) =3D=3D (UINT8)EAmlObjTypeMethodObj= ) { + // The external definition is a method. + return TRUE; + } else { + // The external definition is not a method. + return FALSE; + } + } else { + // The tree is inconsistent. + ASSERT (0); + return FALSE; + } + } + + // This is not a method definition. + return FALSE; +} + +/** Get the index at which the name of the node is stored. + + @param [in] ObjectNode Pointer to an object node. + Must have the AML_IN_NAMESPACE attribute. + @param [out] Index Index of the name in the fixed list of argumen= ts. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +AmlNodeGetNameIndex ( + IN CONST AML_OBJECT_NODE * ObjectNode, + OUT EAML_PARSE_INDEX * Index + ) +{ + EAML_PARSE_INDEX NameIndex; + + if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) || + (ObjectNode->AmlByteEncoding =3D=3D NULL) || + (Index =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + NameIndex =3D ObjectNode->AmlByteEncoding->NameIndex; + + if ((NameIndex > ObjectNode->AmlByteEncoding->MaxIndex) || + (ObjectNode->AmlByteEncoding->Format[NameIndex] !=3D EAmlName)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *Index =3D NameIndex; + + return EFI_SUCCESS; +} + +/** Get the name of the Node. + + Node must be part of the namespace. + + @param [in] ObjectNode Pointer to an object node, + which is part of the namespace. + + @return A pointer to the name. + NULL otherwise. + Return NULL for the root node. +**/ +CHAR8 * +EFIAPI +AmlNodeGetName ( + IN CONST AML_OBJECT_NODE * ObjectNode + ) +{ + EFI_STATUS Status; + EAML_PARSE_INDEX NameIndex; + AML_DATA_NODE * DataNode; + + if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) { + ASSERT (0); + return NULL; + } + + // Get the index at which the name is stored in the fixed arguments list. + Status =3D AmlNodeGetNameIndex (ObjectNode, &NameIndex); + if (EFI_ERROR (Status)) { + ASSERT (0); + return NULL; + } + + // The name is stored in a Data node. + DataNode =3D (AML_DATA_NODE*)ObjectNode->FixedArgs[NameIndex]; + if (IS_AML_DATA_NODE (DataNode) && + (DataNode->DataType =3D=3D EAmlNodeDataTypeNameString)) { + return (CHAR8*)DataNode->Buffer; + } + + /* Return NULL if no name is found. + This can occur if the name of a node is defined as a further + fixed argument. + E.g.: CreateField (BD03, 0x28, Add (ID03 + 0x08), BF33) + ^ + The parser is here. + The parent of the Add statement is the CreateField statement. This + statement defines a name in the AML namespace. This name defined as + the fourth fixed argument. It hasn't been parsed yet. + */ + return NULL; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h b/Dynami= cTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h new file mode 100644 index 0000000000000000000000000000000000000000..3584b572baae5d48f5016c0b889= f557c5ba94d07 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h @@ -0,0 +1,212 @@ +/** @file + AML Node. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_NODE_H_ +#define AML_NODE_H_ + +#include +#include + +/** Create an AML_ROOT_NODE. + This node will be the root of the tree. + + @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT header to copy + the data from. + @param [out] NewRootNodePtr The created AML_ROOT_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateRootNode ( + IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader, + OUT AML_ROOT_NODE ** NewRootNodePtr + ); + +/** Create an AML_OBJECT_NODE. + + @param [in] AmlByteEncoding Byte encoding entry. + @param [in] PkgLength PkgLength of the node if the AmlByteEnco= ding + has the PkgLen attribute. + 0 otherwise. + @param [out] NewObjectNodePtr The created AML_OBJECT_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateObjectNode ( + IN CONST AML_BYTE_ENCODING * AmlByteEncoding, + IN UINT32 PkgLength, + OUT AML_OBJECT_NODE ** NewObjectNodePtr + ); + +/** Create an AML_DATA_NODE. + + @param [in] DataType DataType of the node. + @param [in] Data Pointer to the AML bytecode corresponding = to + this node. Data is copied from there. + @param [in] DataSize Number of bytes to consider at the address + pointed by Data. + @param [out] NewDataNodePtr The created AML_DATA_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateDataNode ( + IN EAML_NODE_DATA_TYPE DataType, + IN CONST UINT8 * Data, + IN UINT32 DataSize, + OUT AML_DATA_NODE ** NewDataNodePtr + ); + +/** Delete a Node. + + @param [in] Node Pointer to a Node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteNode ( + IN AML_NODE_HEADER * Node + ); + +/** Check whether ObjectNode has the input attribute. + This function can be used to check ObjectNode is an object node + at the same time. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Attribute Attribute to check for. + + @retval TRUE The node is an AML object and the attribute is present. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasAttribute ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN AML_OP_ATTRIBUTE Attribute + ); + +/** Check whether ObjectNode has the input OpCode/SubOpcode couple. + + @param [in] ObjectNode Pointer to an object node. + @param [in] OpCode OpCode to check + @param [in] SubOpCode SubOpCode to check + + @retval TRUE The node is an AML object and + the Opcode and the SubOpCode match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeCompareOpCode ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +/** Check whether a Node is an integer node. + + By integer node we mean an object node having one of the following opcod= e: + - AML_BYTE_PREFIX; + - AML_WORD_PREFIX; + - AML_DWORD_PREFIX; + - AML_QWORD_PREFIX. + + @param [in] Node The node to check. + + @retval TRUE The Node is an integer node. + @retval FALSE Otherwise. +*/ +BOOLEAN +EFIAPI +IsIntegerNode ( + IN AML_OBJECT_NODE * Node + ); + +/** Check whether a Node is a ZeroOp, a OneOp or a OnesOp. + + These two objects don't have a data node holding + a value. This require special handling. + + @param [in] Node The node to check. + + @retval TRUE The Node is a ZeroOp or OneOp. + @retval FALSE Otherwise. +*/ +BOOLEAN +EFIAPI +IsSpecialIntegerNode ( + IN AML_OBJECT_NODE * Node + ); + +/** Check whether Node corresponds to a method definition. + + A method definition can be introduced: + - By a method object, having an AML_METHOD_OP OpCode; + - By an external definition of a method, having an AML_EXTERNAL_OP OpCo= de + and an ObjectType byte set to the MethodObj. + + Note: + An alias node, having an AML_ALIAS_OP, can be resolved to a method + definition. This function doesn't handle this case. + + @param [in] Node Node to check whether it is a method definition. + + @retval TRUE The Node is a method definition. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsMethodDefinitionNode ( + IN CONST AML_OBJECT_NODE * Node + ); + +/** Get the index at which the name of the node is stored. + + @param [in] ObjectNode Pointer to an object node. + Must have the AML_IN_NAMESPACE attribute. + @param [out] Index Index of the name in the fixed list of argumen= ts. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +AmlNodeGetNameIndex ( + IN CONST AML_OBJECT_NODE * ObjectNode, + OUT EAML_PARSE_INDEX * Index + ); + +/** Get the name of the Node. + + Node must be part of the namespace. + + @param [in] ObjectNode Pointer to an object node, + which is part of the namespace. + + @return A pointer to the name. + NULL otherwise. + Return NULL for the root node. +**/ +CHAR8 * +EFIAPI +AmlNodeGetName ( + IN CONST AML_OBJECT_NODE * ObjectNode + ); + +#endif // AML_NODE_H_ diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c= b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c new file mode 100644 index 0000000000000000000000000000000000000000..870346c40a5d9df44d01953035c= 760671817b960 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c @@ -0,0 +1,566 @@ +/** @file + AML Node Interface. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include + +/** Returns the tree node type (Root/Object/Data). + + @param [in] Node Pointer to a Node. + + @return The node type. + EAmlNodeUnknown if invalid parameter. +**/ +EAML_NODE_TYPE +EFIAPI +AmlGetNodeType ( + IN AML_NODE_HEADER * Node + ) +{ + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return EAmlNodeUnknown; + } + + return Node->NodeType; +} + +/** Get the RootNode information. + The Node must be a root node. + + @param [in] RootNode Pointer to a root node. + @param [out] SdtHeaderBuffer Buffer to copy the ACPI DSDT/SSDT header= to. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetRootNodeInfo ( + IN AML_ROOT_NODE * RootNode, + OUT EFI_ACPI_DESCRIPTION_HEADER * SdtHeaderBuffer + ) +{ + if (!IS_AML_ROOT_NODE (RootNode) || + (SdtHeaderBuffer =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + SdtHeaderBuffer, + RootNode->SdtHeader, + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + ); + + return EFI_SUCCESS; +} + +/** Get the ObjectNode information. + The Node must be an object node. + + @ingroup NodeInterfaceApi + + @param [in] ObjectNode Pointer to an object node. + @param [out] OpCode Pointer holding the OpCode. + Optional, can be NULL. + @param [out] SubOpCode Pointer holding the SubOpCode. + Optional, can be NULL. + @param [out] PkgLen Pointer holding the PkgLen. + The PkgLen is 0 for nodes + not having the Pkglen attribute. + Optional, can be NULL. + @param [out] IsNameSpaceNode Pointer holding TRUE if the node is defi= ning + or changing the NameSpace scope. + E.g.: The "Name ()" and "Scope ()" ASL + statements add/modify the NameSpace scop= e. + Their corresponding node are NameSpace n= odes. + Optional, can be NULL. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetObjectNodeInfo ( + IN AML_OBJECT_NODE * ObjectNode, + OUT UINT8 * OpCode, OPTIONAL + OUT UINT8 * SubOpCode, OPTIONAL + OUT UINT32 * PkgLen, OPTIONAL + OUT BOOLEAN * IsNameSpaceNode OPTIONAL + ) +{ + if (!IS_AML_OBJECT_NODE (ObjectNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (OpCode !=3D NULL) { + *OpCode =3D ObjectNode->AmlByteEncoding->OpCode; + } + if (SubOpCode !=3D NULL) { + *SubOpCode =3D ObjectNode->AmlByteEncoding->SubOpCode; + } + if (PkgLen !=3D NULL) { + *PkgLen =3D ObjectNode->PkgLen; + } + if (IsNameSpaceNode !=3D NULL) { + *IsNameSpaceNode =3D AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE= ); + } + + return EFI_SUCCESS; +} + +/** Returns the count of the fixed arguments for the input Node. + + @param [in] Node Pointer to an object node. + + @return Number of fixed arguments of the object node. + Return 0 if the node is not an object node. +**/ +UINT8 +AmlGetFixedArgumentCount ( + IN AML_OBJECT_NODE * Node + ) +{ + if (IS_AML_OBJECT_NODE (Node) && + (Node->AmlByteEncoding !=3D NULL)) { + return (UINT8)Node->AmlByteEncoding->MaxIndex; + } + + return 0; +} + +/** Get the data type of the DataNode. + The Node must be a data node. + + @param [in] DataNode Pointer to a data node. + @param [out] DataType Pointer holding the data type of the data buffer. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetNodeDataType ( + IN AML_DATA_NODE * DataNode, + OUT EAML_NODE_DATA_TYPE * DataType + ) +{ + if (!IS_AML_DATA_NODE (DataNode) || + (DataType =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *DataType =3D DataNode->DataType; + + return EFI_SUCCESS; +} + +/** Get the descriptor Id of the resource data element + contained in the DataNode. + + The Node must be a data node. + The Node must have the resource data type, i.e. have the + EAmlNodeDataTypeResourceData data type. + + @param [in] DataNode Pointer to a data node containing a + resource data element. + @param [out] ResourceDataType Pointer holding the descriptor Id of + the resource data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetResourceDataType ( + IN AML_DATA_NODE * DataNode, + OUT AML_RD_HEADER * ResourceDataType + ) +{ + if (!IS_AML_DATA_NODE (DataNode) || + (ResourceDataType =3D=3D NULL) || + (DataNode->DataType !=3D EAmlNodeDataTypeResourceData)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *ResourceDataType =3D AmlRdGetDescId (DataNode->Buffer); + + return EFI_SUCCESS; +} + +/** Get the data buffer and size of the DataNode. + The Node must be a data node. + + BufferSize is always updated to the size of buffer of the DataNode. + + If: + - the content of BufferSize is >=3D to the DataNode's buffer size; + - Buffer is not NULL; + then copy the content of the DataNode's buffer in Buffer. + + @param [in] DataNode Pointer to a data node. + @param [out] Buffer Buffer to write the data to. + Optional, if NULL, only update BufferSiz= e. + @param [in, out] BufferSize Pointer holding: + - At entry, the size of the Buffer; + - At exit, the size of the DataNode's + buffer size. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetDataNodeBuffer ( + IN AML_DATA_NODE * DataNode, + OUT UINT8 * Buffer, OPTIONAL + IN OUT UINT32 * BufferSize + ) +{ + if (!IS_AML_DATA_NODE (DataNode) || + (BufferSize =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if ((*BufferSize >=3D DataNode->Size) && + (Buffer !=3D NULL)) { + CopyMem (Buffer, DataNode->Buffer, DataNode->Size); + } + + *BufferSize =3D DataNode->Size; + + return EFI_SUCCESS; +} + +/** Update the ACPI DSDT/SSDT table header. + + The input SdtHeader information is copied to the tree RootNode. + The table Length field is automatically updated. + The checksum field is only updated when serializing the tree. + + @param [in] RootNode Pointer to a root node. + @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT table header. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRootNode ( + IN AML_ROOT_NODE * RootNode, + IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader + ) +{ + EFI_STATUS Status; + UINT32 Length; + + if (!IS_AML_ROOT_NODE (RootNode) || + (SdtHeader =3D=3D NULL) || + ((SdtHeader->Signature !=3D + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) && + (SdtHeader->Signature !=3D + EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + RootNode->SdtHeader, + SdtHeader, + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + ); + + // Update the Length field. + Status =3D AmlComputeSize ((AML_NODE_HEADER*)RootNode, &Length); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + RootNode->SdtHeader->Length =3D Length + + (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEA= DER); + + return Status; +} + +/** Update an object node representing an integer with a new value. + + The object node must have one of the following OpCodes: + - AML_BYTE_PREFIX + - AML_WORD_PREFIX + - AML_DWORD_PREFIX + - AML_QWORD_PREFIX + - AML_ZERO_OP + - AML_ONE_OP + + The following OpCode is not supported: + - AML_ONES_OP + + @param [in] IntegerOpNode Pointer an object node containing an intege= r. + Must not be an object node with an AML_ONES= _OP + OpCode. + @param [in] NewInteger New integer value to set. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateInteger ( + IN AML_OBJECT_NODE * IntegerOpNode, + IN UINT64 NewInteger + ) +{ + EFI_STATUS Status; + + INT8 ValueWidthDiff; + + if (!IS_AML_OBJECT_NODE (IntegerOpNode) || + (!IsIntegerNode (IntegerOpNode) && + !IsSpecialIntegerNode (IntegerOpNode)) || + AmlNodeCompareOpCode (IntegerOpNode, AML_ONES_OP, 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlNodeSetIntegerValue (IntegerOpNode, NewInteger, &ValueWidt= hDiff); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If the new size is different from the old size, propagate the new siz= e. + if (ValueWidthDiff !=3D 0) { + // Propagate the information. + Status =3D AmlPropagateInformation ( + (AML_NODE_HEADER*)IntegerOpNode, + (ValueWidthDiff > 0) ? TRUE : FALSE, + ABS (ValueWidthDiff), + 0 + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } + + return Status; +} + +/** Update the buffer of a data node. + + Note: The data type of the buffer's content must match the data type of = the + DataNode. This is a hard restriction to prevent undesired behaviou= r. + + @param [in] DataNode Pointer to a data node. + @param [in] DataType Data type of the Buffer's content. + @param [in] Buffer Buffer containing the new data. The content of + the Buffer is copied. + @param [in] Size Size of the Buffer. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_UNSUPPORTED Operation not supporter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateDataNode ( + IN AML_DATA_NODE * DataNode, + IN EAML_NODE_DATA_TYPE DataType, + IN UINT8 * Buffer, + IN UINT32 Size + ) +{ + EFI_STATUS Status; + + UINT32 ExpectedSize; + AML_OBJECT_NODE * ParentNode; + EAML_NODE_DATA_TYPE ExpectedArgType; + EAML_PARSE_INDEX Index; + + if (!IS_AML_DATA_NODE (DataNode) || + (DataType > EAmlNodeDataTypeMax) || + (Buffer =3D=3D NULL) || + (Size =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentNode =3D (AML_OBJECT_NODE*)AmlGetParent ((AML_NODE_HEADER*)DataNod= e); + if (!IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The NewNode and OldNode must have the same type. + // We do not allow to change the argument type of a data node. + // If required, the initial ASL template should be modified + // accordingly. + // It is however possible to interchange a raw buffer and a + // resource data element, since raw data can be misinterpreted + // as a resource data element. + ExpectedArgType =3D DataNode->DataType; + if ((ExpectedArgType !=3D DataType) && + (((ExpectedArgType !=3D EAmlNodeDataTypeRaw) && + (ExpectedArgType !=3D EAmlNodeDataTypeResourceData)) || + ((DataType !=3D EAmlNodeDataTypeRaw) && + (DataType !=3D EAmlNodeDataTypeResourceData)))) { + ASSERT (0); + return EFI_UNSUPPORTED; + } + + // Perform some compatibility checks. + switch (DataType) { + case EAmlNodeDataTypeNameString: + { + // Check the name contained in the Buffer is an AML name + // with the right size. + Status =3D AmlGetNameStringSize ((CONST CHAR8*)Buffer, &ExpectedSize= ); + if (EFI_ERROR (Status) || + (Size !=3D ExpectedSize)) { + ASSERT (0); + return Status; + } + break; + } + case EAmlNodeDataTypeString: + { + ExpectedSize =3D 0; + while (ExpectedSize < Size) { + // Cf ACPI 6.3 specification 20.2.3 Data Objects Encoding. + // AsciiCharList :=3D Nothing | + // AsciiChar :=3D 0x01 - 0x7F + // NullChar :=3D 0x00 + if (Buffer[ExpectedSize] > 0x7F) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + ExpectedSize++; + } + + if (ExpectedSize !=3D Size) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + case EAmlNodeDataTypeUInt: + { + if (AmlIsNodeFixedArgument ((CONST AML_NODE_HEADER*)DataNode, &Index= )) { + if ((ParentNode->AmlByteEncoding =3D=3D NULL) || + (ParentNode->AmlByteEncoding->Format =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // It is not possible to change the size of a fixed length UintX. + // E.g. for PackageOp the first fixed argument is of type EAmlUInt8 + // and represents the count of elements. This type cannot be chang= ed. + if ((ParentNode->AmlByteEncoding->Format[Index] !=3D EAmlObject) && + (DataNode->Size !=3D Size)) { + ASSERT (0); + return EFI_UNSUPPORTED; + } + } + break; + } + case EAmlNodeDataTypeRaw: + { + // Check if the parent node has the byte list flag set. + if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + case EAmlNodeDataTypeResourceData: + { + // The resource data can be either small or large resource data. + // Small resource data must be at least 1 byte. + // Large resource data must be at least as long as the header + // of a large resource data. + if (AML_RD_IS_LARGE (Buffer) && + (Size < sizeof (ACPI_LARGE_RESOURCE_HEADER))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check if the parent node has the byte list flag set. + if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check the size of the buffer is equal to the resource data size + // encoded in the input buffer. + ExpectedSize =3D AmlRdGetSize (Buffer); + if (ExpectedSize !=3D Size) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + case EAmlNodeDataTypeFieldPkgLen: + { + // Check the parent is a FieldNamed field element. + if (!AmlNodeCompareOpCode (ParentNode, AML_FIELD_NAMED_OP, 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + // None and reserved types. + default: + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + break; + } + } // switch + + // If the new size is different from the old size, propagate the new siz= e. + if (DataNode->Size !=3D Size) { + // Propagate the information. + Status =3D AmlPropagateInformation ( + DataNode->NodeHeader.Parent, + (Size > DataNode->Size) ? TRUE : FALSE, + (Size > DataNode->Size) ? + (Size - DataNode->Size) : + (DataNode->Size - Size), + 0 + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Free the old DataNode buffer and allocate a new buffer to store the + // new data. + FreePool (DataNode->Buffer); + DataNode->Buffer =3D AllocateZeroPool (Size); + if (DataNode->Buffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + DataNode->Size =3D Size; + } + + CopyMem (DataNode->Buffer, Buffer, Size); + + return EFI_SUCCESS; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64082): https://edk2.groups.io/g/devel/message/64082 Mute This Topic: https://groups.io/mt/76149139/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64083+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245804700837.3421566964711; Wed, 12 Aug 2020 08:23:24 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id d8tbYY1788612xgEiTtaVfs3; Wed, 12 Aug 2020 08:23:22 -0700 X-Received: from EUR02-VE1-obe.outbound.protection.outlook.com (EUR02-VE1-obe.outbound.protection.outlook.com [40.107.2.52]) by mx.groups.io with SMTP id smtpd.web11.17170.1597245800885554447 for ; Wed, 12 Aug 2020 08:23:21 -0700 X-Received: from DB6P191CA0007.EURP191.PROD.OUTLOOK.COM (2603:10a6:6:28::17) by DB7PR08MB3308.eurprd08.prod.outlook.com (2603:10a6:5:20::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:17 +0000 X-Received: from DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:28:cafe::42) by DB6P191CA0007.outlook.office365.com (2603:10a6:6:28::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:17 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64083+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB5EUR03FT064.mail.protection.outlook.com (10.152.21.199) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:17 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:17 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 3c4eceaa240bbb0a X-CR-MTA-TID: 64aa7808 X-Received: from 02f5b058eaab.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 9D14A255-30DB-4152-99FE-00F443036EB2.1; Wed, 12 Aug 2020 15:23:11 +0000 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 02f5b058eaab.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:11 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OVom0+9UYGUgcWTW5wIOs2IyY7egofjx6QizA/DQvj5k3pMcT1RZznNxisE/ah4XTPloAIjgJd1vukl0Mp6muktA8rvBjUGBMuefqxTHoNz8agbflF/Fc2W0HnfQ6Zl7h3msEcCrdothuKDvdyLs4gsBmn6KkiPwfJ7RaQLBHYlZyjFy2lFwXEmoiMZG4GbgFYn2B7l8a8xtVAgeQI9ru76hXHZa3kLDqOvFGzdW5pEBmSlyCwsnCtmpXTzkaPrLzVgLi2QASocJrVvRsUSx8sqMluspgY+TUPQbxjmT7fKv7B3I8Q4ilqXARxtLa8YwkMXK78h0u5N2++mNiiksUQ== 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-SenderADCheck; bh=4Co9myQ9Bt5agoiQ/GImR8hmud2iBSbD8xWYbH/DVnk=; b=eTDqexnsKoKR9zYV+wAevvYb/DAQvjjMKcA2OWszWQfc8c7eCzXlsaIrCRql0Ad8Ka1DGaQD0Uy9qAhZxO0CqJsJFH1lOUmdXEaOE+DyOYolK9FnvwQg80kEJe0kbEbk5z6IOOHODUuGeFfHLMqNYd7dGgjojsw2pDXuWoysVEkRwBxkC1XsrzfSF3fy2aE9ZRtF1ygprM7gvWu8+mfVATgeEpOJm6SCqE/zAMgTL1Qf8AZj5TOptnvdPUVJlAlj84FfrUR4/W1uvhcV+6Tena8nowMYEL5hM/Ed3CRqTaoutEK8UjiwigLIDKNUJSnsZ1MkxqAb8vKeXC0kPu7ddg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB8PR06CA0010.eurprd06.prod.outlook.com (2603:10a6:10:100::23) by VI1PR08MB2800.eurprd08.prod.outlook.com (2603:10a6:802:1b::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.20; Wed, 12 Aug 2020 15:23:10 +0000 X-Received: from DB5EUR03FT035.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:100:cafe::35) by DB8PR06CA0010.outlook.office365.com (2603:10a6:10:100::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:10 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT035.mail.protection.outlook.com (10.152.20.65) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:10 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:22:58 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:22:57 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 05/30] DynamicTablesPkg: AML tree interface Date: Wed, 12 Aug 2020 16:22:11 +0100 Message-ID: <20200812152236.31164-6-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5ee8e880-9c3b-403f-6866-08d83ed3a361 X-MS-TrafficTypeDiagnostic: VI1PR08MB2800:|DB7PR08MB3308: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:7219;OLM:7219; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: ZU9mZMTP3gTOBKG3bQ51lyxVVwKADMwS3JZuCAlDgWDvYKj69xmwgyM9tpLCuTOTON8dISrtaEJcXUH4Kh7+jUROcL1HVsjwb4sY+gOg2c5FiFTnHgdErwg6sUHVqbRXqRSk6jbjhRphgZuChyaGpuapWWwLg+eEPUu7ZZh/aYs0xkKtmuK4uF5suQmVoZVSeo2dnBxfc9fv499PBbS9cEDuQtotVy03BVBVIeI3XxZu+NdBZkdSJCFzcfCCoYGRa5POq639KUYPSf02iwQkhjtFZiy9xTHG75U/2PoTtEzQyBvLKfNr2v3wTg1PXV06ZahXF27yaJZ7UPJKZeiBvqfw6s/41veKsXxNjIE/cNsUsftrjtGDBg6cnmUAj451/2U3hfvCU8z1fIup/excvQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(136003)(346002)(376002)(39860400002)(396003)(46966005)(316002)(478600001)(70206006)(54906003)(47076004)(36756003)(6666004)(336012)(70586007)(82740400003)(44832011)(2906002)(7696005)(8676002)(86362001)(6916009)(81166007)(82310400002)(426003)(356005)(8936002)(30864003)(186003)(83380400001)(1076003)(5660300002)(26005)(2616005)(4326008);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB2800 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 512f83e4-7e22-4f29-7e7a-08d83ed39f1c X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:17.2936 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5ee8e880-9c3b-403f-6866-08d83ed3a361 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: DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3308 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: CtWRw2MjyfeUkn5PCNhlDQ8Jx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245802; bh=k0x+zrYjiO8P56NTM3a7/rO5tweGeRLJ240dumxAqnc=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=H3Co62OXXBcuEK6t7eoND/vkXUocxAVrQSaD39BqgeYA/jMOtqAvRwaHZ7/VLiTBHCH ssjF6eRDjkKapCcRTcKmBoMgLgSEWLrog3pEPq4oXffkvZidtXDRcm8e3+tVJpH6/Bnum sjizuTLknJYy/NdDCeS8gW2NqvQmRkigP/w= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML tree is composite and has the following node types: - Root node. - Object node. - Data node. These nodes are part of the Fixed Arguments or the Variable arguments list in the AML tree. The AML tree interface provides functions to manage the fixed and the variable argument nodes in the AML tree. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c | 1047 +++++++++++++= +++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h | 127 +++ 2 files changed, 1174 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c b/Dynami= cTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c new file mode 100644 index 0000000000000000000000000000000000000000..65dad95da2760c512563a5152ba= 4acf42d555019 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c @@ -0,0 +1,1047 @@ +/** @file + AML Tree. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include + +/** Get the parent node of the input Node. + + @param [in] Node Pointer to a node. + + @return The parent node of the input Node. + NULL otherwise. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetParent ( + IN AML_NODE_HEADER * Node + ) +{ + if (IS_AML_DATA_NODE (Node) || + IS_AML_OBJECT_NODE (Node)) { + return Node->Parent; + } + + return NULL; +} + +/** Get the root node from any node of the tree. + This is done by climbing up the tree until the root node is reached. + + @param [in] Node Pointer to a node. + + @return The root node of the tree. + NULL if error. +*/ +AML_ROOT_NODE * +EFIAPI +AmlGetRootNode ( + IN CONST AML_NODE_HEADER * Node + ) +{ + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return NULL; + } + + while (!IS_AML_ROOT_NODE (Node)) { + Node =3D Node->Parent; + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return NULL; + } + } + return (AML_ROOT_NODE*)Node; +} + +/** Get the node at the input Index in the fixed argument list of the input + ObjectNode. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Index The Index of the fixed argument to get. + + @return The node at the input Index in the fixed argument list + of the input ObjectNode. + NULL otherwise, e.g. if the node is not an object node, or no + node is available at this Index. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetFixedArgument ( + IN AML_OBJECT_NODE * ObjectNode, + IN EAML_PARSE_INDEX Index + ) +{ + if (IS_AML_OBJECT_NODE (ObjectNode)) { + if (Index < (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode)) { + return ObjectNode->FixedArgs[Index]; + } + } + + return NULL; +} + +/** Check whether the input Node is in the fixed argument list of its pare= nt + node. + + If so, IndexPtr contains this Index. + + @param [in] Node Pointer to a Node. + @param [out] IndexPtr Pointer holding the Index of the Node in + its parent's fixed argument list. + + @retval TRUE The node is a fixed argument and the index + in IndexPtr is valid. + @retval FALSE The node is not a fixed argument. +**/ +BOOLEAN +EFIAPI +AmlIsNodeFixedArgument ( + IN CONST AML_NODE_HEADER * Node, + OUT EAML_PARSE_INDEX * IndexPtr + ) +{ + AML_NODE_HEADER * ParentNode; + + EAML_PARSE_INDEX Index; + EAML_PARSE_INDEX MaxIndex; + + if ((IndexPtr =3D=3D NULL) || + (!IS_AML_DATA_NODE (Node) && + !IS_AML_OBJECT_NODE (Node))) { + ASSERT (0); + return FALSE; + } + + ParentNode =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (IS_AML_ROOT_NODE (ParentNode)) { + return FALSE; + } else if (IS_AML_DATA_NODE (ParentNode)) { + // Tree is inconsistent. + ASSERT (0); + return FALSE; + } + + // Check whether the Node is in the fixed argument list. + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)ParentNode + ); + for (Index =3D EAmlParseIndexTerm0; Index < MaxIndex; Index++) { + if (AmlGetFixedArgument ((AML_OBJECT_NODE*)ParentNode, Index) =3D=3D N= ode) { + *IndexPtr =3D Index; + return TRUE; + } + } + + return FALSE; +} + +/** Set the fixed argument of the ObjectNode at the Index to the NewNode. + + It is the caller's responsibility to save the old node, if desired, + otherwise the reference to the old node will be lost. + If NewNode is not NULL, set its parent to ObjectNode. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Index Index in the fixed argument list of + the ObjectNode to set. + @param [in] NewNode Pointer to the NewNode. + Can be NULL, a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlSetFixedArgument ( + IN AML_OBJECT_NODE * ObjectNode, + IN EAML_PARSE_INDEX Index, + IN AML_NODE_HEADER * NewNode + ) +{ + if (IS_AML_OBJECT_NODE (ObjectNode) = && + (Index <=3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode))= && + ((NewNode =3D=3D NULL) = || + IS_AML_OBJECT_NODE (NewNode) = || + IS_AML_DATA_NODE (NewNode))) { + ObjectNode->FixedArgs[Index] =3D NewNode; + + // If NewNode is a data node or an object node, set its parent. + if (NewNode !=3D NULL) { + NewNode->Parent =3D (AML_NODE_HEADER*)ObjectNode; + } + + return EFI_SUCCESS; + } + + ASSERT (0); + return EFI_INVALID_PARAMETER; +} + +/** If the given AML_NODE_HEADER has a variable list of arguments, + return a pointer to this list. + Return NULL otherwise. + + @param [in] Node Pointer to the AML_NODE_HEADER to check. + + @return The list of variable arguments if there is one. + NULL otherwise. +**/ +LIST_ENTRY * +EFIAPI +AmlNodeGetVariableArgList ( + IN CONST AML_NODE_HEADER * Node + ) +{ + if (IS_AML_ROOT_NODE (Node)) { + return &(((AML_ROOT_NODE*)Node)->VariableArgs); + } else if (IS_AML_OBJECT_NODE (Node)) { + return &(((AML_OBJECT_NODE*)Node)->VariableArgs); + } + return NULL; +} + +/** Remove the Node from its parent's variable list of arguments. + + The function will fail if the Node is in its parent's fixed + argument list. + The Node is not deleted. The deletion is done separately + from the removal. + + @param [in] Node Pointer to a Node. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlRemoveNodeFromVarArgList ( + IN AML_NODE_HEADER * Node + ) +{ + EFI_STATUS Status; + AML_NODE_HEADER * ParentNode; + UINT32 Size; + + if ((!IS_AML_DATA_NODE (Node) && + !IS_AML_OBJECT_NODE (Node))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentNode =3D AmlGetParent (Node); + if (!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check the node is in its parent variable list of arguments. + if (!IsNodeInList ( + AmlNodeGetVariableArgList (ParentNode), + &Node->Link)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Unlink Node from the tree. + RemoveEntryList (&Node->Link); + InitializeListHead (&Node->Link); + Node->Parent =3D NULL; + + // Get the size of the node removed. + Status =3D AmlComputeSize (Node, &Size); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the information. + Status =3D AmlPropagateInformation (ParentNode, FALSE, Size, 1); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Detach the Node from the tree. + + The function will fail if the Node is in its parent's fixed + argument list. + The Node is not deleted. The deletion is done separately + from the removal. + + @param [in] Node Pointer to a Node. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDetachNode ( + IN AML_NODE_HEADER * Node + ) +{ + return AmlRemoveNodeFromVarArgList (Node); +} + +/** Add the NewNode to the head of the variable list of arguments + of the ParentNode. + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddHead ( + IN AML_NODE_HEADER * ParentNode, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + UINT32 NewSize; + LIST_ENTRY * ChildrenList; + + // Check arguments and that NewNode is not already attached to a tree. + // ParentNode !=3D Data Node AND NewNode !=3D Root Node AND NewNode !=3D= attached. + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Insert it at the head of the list. + ChildrenList =3D AmlNodeGetVariableArgList (ParentNode); + if (ChildrenList =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + InsertHeadList (ChildrenList, &NewNode->Link); + NewNode->Parent =3D ParentNode; + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation (ParentNode, TRUE, NewSize, 1); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Add the NewNode to the tail of the variable list of arguments + of the ParentNode. + + NOTE: This is an internal function which does not propagate the size + when a new node is added. + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddTailInternal ( + IN AML_NODE_HEADER * ParentNode, + IN AML_NODE_HEADER * NewNode + ) +{ + LIST_ENTRY * ChildrenList; + + // Check arguments and that NewNode is not already attached to a tree. + // ParentNode !=3D Data Node AND NewNode !=3D Root Node AND NewNode !=3D= attached. + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Insert it at the tail of the list. + ChildrenList =3D AmlNodeGetVariableArgList (ParentNode); + if (ChildrenList =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + InsertTailList (ChildrenList, &NewNode->Link); + NewNode->Parent =3D ParentNode; + + return EFI_SUCCESS; +} + +/** Add the NewNode to the tail of the variable list of arguments + of the ParentNode. + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddTail ( + IN AML_NODE_HEADER * ParentNode, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + UINT32 NewSize; + + // Add the NewNode and check arguments. + Status =3D AmlVarListAddTailInternal (ParentNode, NewNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation (ParentNode, TRUE, NewSize, 1); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Add the NewNode before the Node in the list of variable + arguments of the Node's parent. + + @param [in] Node Pointer to a node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddBefore ( + IN AML_NODE_HEADER * Node, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + AML_NODE_HEADER * ParentNode; + UINT32 NewSize; + + // Check arguments and that NewNode is not already attached to a tree. + if ((!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentNode =3D AmlGetParent (Node); + if (!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Insert it before the input Node. + InsertTailList (&Node->Link, &NewNode->Link); + NewNode->Parent =3D ParentNode; + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation (ParentNode, TRUE, NewSize, 1); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Add the NewNode after the Node in the variable list of arguments + of the Node's parent. + + @param [in] Node Pointer to a node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddAfter ( + IN AML_NODE_HEADER * Node, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + AML_NODE_HEADER * ParentNode; + UINT32 NewSize; + + // Check arguments and that NewNode is not already attached to a tree. + if ((!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentNode =3D AmlGetParent (Node); + if (!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Insert the new node after the input Node. + InsertHeadList (&Node->Link, &NewNode->Link); + NewNode->Parent =3D ParentNode; + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation (ParentNode, TRUE, NewSize, 1); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Append a Resource Data node to the BufferOpNode. + + The Resource Data node is added at the end of the variable + list of arguments of the BufferOpNode, but before the End Tag. + If no End Tag is found, the function returns an error. + + @param [in] BufferOpNode Buffer node containing resource data element= s. + @param [in] NewRdNode The new Resource Data node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlAppendRdNode ( + IN AML_OBJECT_NODE * BufferOpNode, + IN AML_DATA_NODE * NewRdNode + ) +{ + EFI_STATUS Status; + AML_DATA_NODE * CurrRdNode; + AML_RD_HEADER RdDataType; + + if (!AmlNodeCompareOpCode (BufferOpNode, AML_BUFFER_OP, 0) || + !IS_AML_DATA_NODE (NewRdNode) || + (NewRdNode->DataType !=3D EAmlNodeDataTypeResourceData)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the first Resource data node in the variable list of + // argument of the BufferOp node. + CurrRdNode =3D (AML_DATA_NODE*)AmlGetNextVariableArgument ( + (AML_NODE_HEADER*)BufferOpNode, + NULL + ); + if ((CurrRdNode =3D=3D NULL) || + !IS_AML_DATA_NODE (CurrRdNode) || + (CurrRdNode->DataType !=3D EAmlNodeDataTypeResourceData)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Iterate through the Resource Data nodes to find the End Tag. + while (TRUE) { + Status =3D AmlGetResourceDataType (CurrRdNode, &RdDataType); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If the Resource Data is an End Tag, + // add the new node before and return. + if (AmlRdCompareDescId ( + &RdDataType, + AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))= ) { + Status =3D AmlVarListAddBefore ( + (AML_NODE_HEADER*)CurrRdNode, + (AML_NODE_HEADER*)NewRdNode) + ; + if (EFI_ERROR (Status)) { + ASSERT (0); + } + return Status; + } + + // Get the next Resource Data node. + // If this was the last node and no End Tag was found, return error. + // It is possible to have only one Resource Data in a BufferOp, + // but it should not be possible to add a new Resource Data in the list + // in this case. + CurrRdNode =3D (AML_DATA_NODE*)AmlGetSiblingVariableArgument ( + (AML_NODE_HEADER*)CurrRdNode + ); + if (!IS_AML_DATA_NODE (CurrRdNode) || + (CurrRdNode->DataType !=3D EAmlNodeDataTypeResourceData)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } // while +} + +/** Replace the fixed argument at the Index of the ParentNode with the New= Node. + + Note: This function unlinks the OldNode from the tree. It is the callers + responsibility to delete the OldNode if needed. + + @param [in] ParentNode Pointer to the parent node. + Must be an object node. + @param [in] Index Index of the fixed argument to replace. + @param [in] NewNode The new node to insert. + Must be an object node or a data node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlReplaceFixedArgument ( + IN AML_OBJECT_NODE * ParentNode, + IN EAML_PARSE_INDEX Index, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * OldNode; + UINT32 NewSize; + UINT32 OldSize; + AML_PARSE_FORMAT FixedArgType; + + // Check arguments and that NewNode is not already attached to a tree. + if (!IS_AML_OBJECT_NODE (ParentNode) || + (!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Perform some compatibility checks between NewNode and OldNode. + FixedArgType =3D ParentNode->AmlByteEncoding->Format[Index]; + switch (FixedArgType) { + case EAmlFieldPkgLen: + { + // A FieldPkgLen can only have a parent node with the + // AML_IS_FIELD_ELEMENT flag. + if (!AmlNodeHasAttribute ( + (AML_OBJECT_NODE*)ParentNode, + AML_HAS_FIELD_LIST)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + // Fall through. + } + + case EAmlUInt8: + case EAmlUInt16: + case EAmlUInt32: + case EAmlUInt64: + case EAmlName: + case EAmlString: + { + // A uint, a name, a string and a FieldPkgLen can only be replaced b= y a + // data node of the same type. + // Note: This condition might be too strict, but safer. + if (!IS_AML_DATA_NODE (NewNode) || + (((AML_DATA_NODE*)NewNode)->DataType !=3D + AmlTypeToNodeDataType (FixedArgType))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + + case EAmlObject: + { + // If it's an object node, the grammar is too complex to do any chec= k. + break; + } + + case EAmlNone: + default: + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + break; + } + } // switch + + // Replace the OldNode with the NewNode. + OldNode =3D AmlGetFixedArgument (ParentNode, Index); + if (!IS_AML_NODE_VALID (OldNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Unlink the old node. + // Note: This function unlinks the OldNode from the tree. It is the call= ers + // responsibility to delete the OldNode if needed. + OldNode->Parent =3D NULL; + + Status =3D AmlSetFixedArgument (ParentNode, Index, NewNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the size of the OldNode. + Status =3D AmlComputeSize (OldNode, &OldSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation ( + (AML_NODE_HEADER*)ParentNode, + (NewSize > OldSize) ? TRUE : FALSE, + (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSize= ), + 0 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Replace the OldNode, which is in a variable list of arguments, + with the NewNode. + + Note: This function unlinks the OldNode from the tree. It is the callers + responsibility to delete the OldNode if needed. + + @param [in] OldNode Pointer to the node to replace. + Must be a data node or an object node. + @param [in] NewNode The new node to insert. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlReplaceVariableArgument ( + IN AML_NODE_HEADER * OldNode, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + UINT32 NewSize; + UINT32 OldSize; + EAML_PARSE_INDEX Index; + + AML_DATA_NODE * NewDataNode; + AML_NODE_HEADER * ParentNode; + LIST_ENTRY * NextLink; + + // Check arguments, that NewNode is not already attached to a tree, + // and that OldNode is attached and not in a fixed list of arguments. + if ((!IS_AML_DATA_NODE (OldNode) && + !IS_AML_OBJECT_NODE (OldNode)) || + (!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode) || + AML_NODE_IS_DETACHED (OldNode) || + AmlIsNodeFixedArgument (OldNode, &Index)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentNode =3D AmlGetParent (OldNode); + if (!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + NewDataNode =3D (AML_DATA_NODE*)NewNode; + + // Check attributes if the parent node is an object node. + if (IS_AML_OBJECT_NODE (ParentNode)) { + // A child node of a node with the HAS_CHILD flag must be either a + // data node or an object node. This has already been checked. So, + // check for other cases. + + if (AmlNodeHasAttribute ((AML_OBJECT_NODE*)ParentNode, AML_HAS_BYTE_LI= ST)) { + if (!IS_AML_DATA_NODE (NewNode) || + ((NewDataNode->DataType !=3D EAmlNodeDataTypeRaw) && + (NewDataNode->DataType !=3D EAmlNodeDataTypeResourceData))) { + // A child node of a node with the BYTE_LIST flag must be a data n= ode, + // containing raw data or a resource data. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } else if (AmlNodeHasAttribute ( + (AML_OBJECT_NODE*)ParentNode, + AML_HAS_FIELD_LIST)) { + if (!AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)NewNode, + AML_IS_FIELD_ELEMENT)) { + // A child node of a node with the FIELD_LIST flag must be an obje= ct + // node with AML_IS_FIELD_ELEMENT flag. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + } else { + // Parent node is a root node. + // A root node cannot have a data node as its child. + if (!IS_AML_DATA_NODE (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + // Unlink OldNode from the tree. + NextLink =3D RemoveEntryList (&OldNode->Link); + InitializeListHead (&OldNode->Link); + OldNode->Parent =3D NULL; + + // Add the NewNode. + InsertHeadList (NextLink, &NewNode->Link); + NewNode->Parent =3D ParentNode; + + // Get the size of the OldNode. + Status =3D AmlComputeSize (OldNode, &OldSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the size of the NewNode. + Status =3D AmlComputeSize (NewNode, &NewSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the new information. + Status =3D AmlPropagateInformation ( + ParentNode, + (NewSize > OldSize) ? TRUE : FALSE, + (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSiz= e), + 0 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Replace the OldNode by the NewNode. + + Note: This function unlinks the OldNode from the tree. It is the callers + responsibility to delete the OldNode if needed. + + @param [in] OldNode Pointer to the node to replace. + Must be a data node or an object node. + @param [in] NewNode The new node to insert. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlReplaceArgument ( + IN AML_NODE_HEADER * OldNode, + IN AML_NODE_HEADER * NewNode + ) +{ + EFI_STATUS Status; + AML_NODE_HEADER * ParentNode; + EAML_PARSE_INDEX Index; + + // Check arguments and that NewNode is not already attached to a tree. + if ((!IS_AML_DATA_NODE (OldNode) && + !IS_AML_OBJECT_NODE (OldNode)) || + (!IS_AML_DATA_NODE (NewNode) && + !IS_AML_OBJECT_NODE (NewNode)) || + !AML_NODE_IS_DETACHED (NewNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // ParentNode can be a root node or an object node. + ParentNode =3D AmlGetParent (OldNode); + if (!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (AmlIsNodeFixedArgument (OldNode, &Index)) { + // OldNode is in its parent's fixed argument list at the Index. + Status =3D AmlReplaceFixedArgument ( + (AML_OBJECT_NODE*)ParentNode, + Index, + NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } else { + // OldNode is not in its parent's fixed argument list. + // It must be in its variable list of arguments. + Status =3D AmlReplaceVariableArgument (OldNode, NewNode); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} + +/** Delete a Node and its children. + + The Node must be removed from the tree first, + or must be the root node. + + @param [in] Node Pointer to the node to delete. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteTree ( + IN AML_NODE_HEADER * Node + ) +{ + EFI_STATUS Status; + + EAML_PARSE_INDEX Index; + EAML_PARSE_INDEX MaxIndex; + + AML_NODE_HEADER * Arg; + LIST_ENTRY * StartLink; + LIST_ENTRY * CurrentLink; + LIST_ENTRY * NextLink; + + // Check that the node being deleted is unlinked. + // When removing the node, its parent pointer and + // its lists data structure are reset with + // InitializeListHead. Thus it must be detached + // from the tree to avoid memory leaks. + if (!IS_AML_NODE_VALID (Node) || + !AML_NODE_IS_DETACHED (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // 1. Recursively detach and delete the fixed arguments. + // Iterate through the fixed list of arguments. + if (IS_AML_OBJECT_NODE (Node)) { + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)Node + ); + for (Index =3D EAmlParseIndexTerm0; Index < MaxIndex; Index++) { + Arg =3D AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index); + if (Arg =3D=3D NULL) { + // A fixed argument is missing. The tree is inconsistent. + // Note: During CodeGeneration, the fixed arguments should be set + // with an incrementing index, and then the variable argumen= ts + // should be added. This allows to free as many nodes as + // possible if a crash occurs. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Remove the node from the fixed argument list. + Arg->Parent =3D NULL; + Status =3D AmlSetFixedArgument ((AML_OBJECT_NODE*)Node, Index, NULL); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlDeleteTree (Arg); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } + + // 2. Recursively detach and delete the variable arguments. + // Iterate through the variable list of arguments. + StartLink =3D AmlNodeGetVariableArgList (Node); + if (StartLink !=3D NULL) { + NextLink =3D StartLink->ForwardLink; + while (NextLink !=3D StartLink) { + CurrentLink =3D NextLink; + + // Unlink the node from the tree. + NextLink =3D RemoveEntryList (CurrentLink); + InitializeListHead (CurrentLink); + ((AML_NODE_HEADER*)CurrentLink)->Parent =3D NULL; + + Status =3D AmlDeleteTree ((AML_NODE_HEADER*)CurrentLink); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // while + } + + // 3. Delete the node. + Status =3D AmlDeleteNode (Node); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h b/Dynami= cTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h new file mode 100644 index 0000000000000000000000000000000000000000..0b3803c47c7f468ca248d717e72= d161812d485d8 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h @@ -0,0 +1,127 @@ +/** @file + AML Tree. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_TREE_H_ +#define AML_TREE_H_ + +#include + +/** Get the root node from any node of the tree. + This is done by climbing up the tree until the root node is reached. + + @param [in] Node Pointer to a node. + + @return The root node of the tree. + NULL if error. +*/ +AML_ROOT_NODE * +EFIAPI +AmlGetRootNode ( + IN CONST AML_NODE_HEADER * Node + ); + +/** Check whether the input Node is in the fixed argument list of its pare= nt + node. + + If so, IndexPtr contains this Index. + + @param [in] Node Pointer to a Node. + @param [out] IndexPtr Pointer holding the Index of the Node in + its parent's fixed argument list. + + @retval TRUE The node is a fixed argument and the index + in IndexPtr is valid. + @retval FALSE The node is not a fixed argument. +**/ +BOOLEAN +EFIAPI +AmlIsNodeFixedArgument ( + IN CONST AML_NODE_HEADER * Node, + OUT EAML_PARSE_INDEX * IndexPtr + ); + +/** Set the fixed argument of the ObjectNode at the Index to the NewNode. + + It is the caller's responsibility to save the old node, if desired, + otherwise the reference to the old node will be lost. + If NewNode is not NULL, set its parent to ObjectNode. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Index Index in the fixed argument list of + the ObjectNode to set. + @param [in] NewNode Pointer to the NewNode. + Can be NULL, a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlSetFixedArgument ( + IN AML_OBJECT_NODE * ObjectNode, + IN EAML_PARSE_INDEX Index, + IN AML_NODE_HEADER * NewNode + ); + +/** If the given AML_NODE_HEADER has a variable list of arguments, + return a pointer to this list. + Return NULL otherwise. + + @param [in] Node Pointer to the AML_NODE_HEADER to check. + + @return The list of variable arguments if there is one. + NULL otherwise. +**/ +LIST_ENTRY * +EFIAPI +AmlNodeGetVariableArgList ( + IN CONST AML_NODE_HEADER * Node + ); + +/** Add the NewNode to the tail of the variable list of arguments + of the ParentNode. + + NOTE: This is an internal function which does not propagate the size + when a new node is added. + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddTailInternal ( + IN AML_NODE_HEADER * ParentNode, + IN AML_NODE_HEADER * NewNode + ); + +/** Replace the OldNode by the NewNode. + + Note: This function unlinks the OldNode from the tree. It is the callers + responsibility to delete the OldNode if needed. + + @param [in] OldNode Pointer to the node to replace. + Must be a data node or an object node. + @param [in] NewNode The new node to insert. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlReplaceArgument ( + IN AML_NODE_HEADER * OldNode, + IN AML_NODE_HEADER * NewNode + ); + +#endif // AML_TREE_H_ + --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64083): https://edk2.groups.io/g/devel/message/64083 Mute This Topic: https://groups.io/mt/76149143/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64084+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245808614550.2136495427333; Wed, 12 Aug 2020 08:23:28 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id jq5eYY1788612x6hIcmeJlgm; Wed, 12 Aug 2020 08:23:27 -0700 X-Received: from FRA01-MR2-obe.outbound.protection.outlook.com (FRA01-MR2-obe.outbound.protection.outlook.com [40.107.9.87]) by mx.groups.io with SMTP id smtpd.web10.17190.1597245806766218395 for ; Wed, 12 Aug 2020 08:23:27 -0700 X-Received: from AM5PR0402CA0013.eurprd04.prod.outlook.com (2603:10a6:203:90::23) by PR2PR08MB4923.eurprd08.prod.outlook.com (2603:10a6:101:24::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:90:cafe::3) by AM5PR0402CA0013.outlook.office365.com (2603:10a6:203:90::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23: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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64084+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT059.mail.protection.outlook.com (10.152.17.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:23 +0000 X-Received: ("Tessian outbound e8cdb8c6f386:v64"); Wed, 12 Aug 2020 15:23:23 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 8052b62c2e12e684 X-CR-MTA-TID: 64aa7808 X-Received: from 747c73290921.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id D550BC5A-E859-406E-BA1F-AF5C0C2BD507.1; Wed, 12 Aug 2020 15:23:15 +0000 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 747c73290921.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:15 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Cuq9ATYsG+AfvbHWWFDkLfvgYDjt9ilr/Bigx4YZR+H2ymDQ/8FyFY7u59oq8azfc9kTnEt3WK9XGJ2bptWhR0rN+jBtiD4oZEF4ncqF1AJESVG5+5tEmjqbivHOVvApZtkUGcemfaANSX5YZc4cvtpZe9cq0xNmrCNfJraHD+N610wn7vA0UH467uHbyN0d0S+JW96+HckMuXyrIYrz4xk0VOinmjMXu49mGK+vmgB30Z636ML/3A0ULjzcAYDZ75Yw64a2kH78XuMWzPWD+zfLlwJHz/4qZ5I6opBw9XRp4NR/+0tga7uxZ0i5Qs3IMj3qZslmvgXRdMZAIKIMPQ== 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-SenderADCheck; bh=eFINIP8or9Zm+z9FJnNPRe2ZC6jbWsMUmHWEYsIZ6Ww=; b=DdXV5yz3TTK8tDD5qewW0ErVI3u0jAIBHUhneg9foBQ5clXpvOS0YM1qyvmklziDISJq+G33urQlLymE+Brl6Vcm7L6QTfGJVT+Mnpn/l3+Z+4Njq6bpDATgDnte/FcBRi6qInAkTUSqA9c2JrRjaxCRTppD7C+/37t0t3aSkzOvLIqQ+3mZ1bOlq0k9OwCtbN+yfzZRZQygQfDGQvgUWPbQS7QJyPNoteiaTg8Gf/z9851FOi2xLX9xwD7hoOoMQqsrz2O+dtaoyV34AqHmvXj5XfWEWmltYQ37iFggJJ83NDh87G5qj/fqrxayM1YsbbTGyIBQKCveMo+v8RoFQQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB8PR06CA0002.eurprd06.prod.outlook.com (2603:10a6:10:100::15) by DBBPR08MB4299.eurprd08.prod.outlook.com (2603:10a6:10:ce::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16; Wed, 12 Aug 2020 15:23:11 +0000 X-Received: from DB5EUR03FT035.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:100:cafe::dc) by DB8PR06CA0002.outlook.office365.com (2603:10a6:10:100::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:11 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT035.mail.protection.outlook.com (10.152.20.65) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:11 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:05 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:04 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 06/30] DynamicTablesPkg: AML tree enumerator Date: Wed, 12 Aug 2020 16:22:12 +0100 Message-ID: <20200812152236.31164-7-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4be888a2-5af3-43a8-ac9c-08d83ed3a760 X-MS-TrafficTypeDiagnostic: DBBPR08MB4299:|PR2PR08MB4923: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:6430;OLM:6430; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: XPptf+s9mB3r5mi58zid+IXCMicYV+v7QZKA98Wpvhc+G8+e7+/vNZv87zjGO4og+QSOy8Cc0s0y9eu+TFHjb/G/mqDJPz9JrR7sCY3qDjpT/VAnUwra5MNqnTIhbgQLg8juXX3QFYvJ02MRvI4ZHcFfPrPcdE46I0mHFS6BykqJNFIkgrppcM9U3EXs7dMQqFJ9o/+gr7Ojs+G2WTAqmCgx6CFq9m0BbC0o/4LcfAEvPAzZ4LW7NAwVgZOCN439sA9VrpqjgHJMHYZ6sdZ0lNdPBci6RH/2U3CKbvx9yXHS9pymVPdiMIBeCoX28mwcYCouM0t6HfTQrbXw0QRsAVpCfT9mRtEvn2Vd9JNt6k5EHKNXaU38XkMNfkpsr0p4pqbyWTWQKDP7gG7E5MiIKg== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(136003)(396003)(39860400002)(376002)(346002)(46966005)(186003)(7696005)(47076004)(70206006)(81166007)(70586007)(26005)(478600001)(5660300002)(6666004)(44832011)(1076003)(83380400001)(2616005)(6916009)(426003)(82740400003)(8936002)(2906002)(356005)(36756003)(82310400002)(8676002)(54906003)(336012)(4326008)(316002)(86362001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4299 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 44a655a7-0a2f-4e11-6684-08d83ed3a00c X-Microsoft-Antispam-Message-Info: QBspPfG/rX5fJSIvBKhmpRtb98p8yRml5FulN4kWNg4z+4QSyhwFj7X+azlB//Y6CVRtt03Q9lK9Gk0ORAXZcU8qCAi/UGUZ4yllzRCuesnEhGLiuuOwlMuCRn95qY+Yi2z29T6n/aStZzlESy57phgArC5eoGP/vfRRyukIg3MVI9Fgnp3VjhYF6dNqQWULMHn6FCq916xgKfchGyXcYBFrPGwXt0HK7pTv0dGxQwjmbQap+uVx6GTvR9mCM1lqoKswJkDHzkG3OqnlaFAhhyuAaGMwtc0QDULc7uuOGPE+cIRV2ziAsRAvaAHZ1dLjOV9KPowiXCSN3VVJY/Hb24zhpzVSWbyALEDsfYpJi46eyPzIjzZFMvjoyTVxhPYVJfgMXSlrTZ95x3xgoE+i2g== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:23.9527 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4be888a2-5af3-43a8-ac9c-08d83ed3a760 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: AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR2PR08MB4923 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: NofFOo06dX3UOEnPQwhK1619x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245807; bh=vD/jr/y74NMGTyao+MTgmpSwHytlixGWpwWtJeBiP3Q=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=KtG0eh2FHsGInrJIXxzWiv16+bPUQETYI0rtGhLXz7JVBsSF26ODHyG5nWed6TQd25L F4U9L4fGxqtf3k3scKTLqa8/LF0oXPXHF9tpRcT0AD7u7uVRrOEGuLbbY1UfgghNNS8MM Scc+O3t578gGIC85Umj28xAaJ3JU/fRS/Ow= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML tree enumerator interface allows enumeration of the nodes in the AML tree. The enumerator interface can be useful to search, serialise, print etc. the nodes in the AML tree. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c | 98 +++++= +++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.= c b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c new file mode 100644 index 0000000000000000000000000000000000000000..3eeb7253bfb647f5430a89a87e8= a196c453abe71 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c @@ -0,0 +1,98 @@ +/** @file + AML Tree Enumerator. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include + +/** Enumerate all nodes of the subtree under the input Node in the AML + bytestream order (i.e. in a depth first order), and call the CallBack + function with the input Context. + The prototype of the Callback function is EDKII_AML_TREE_ENUM_CALLBACK. + + @param [in] Node Enumerate nodes of the subtree under this No= de. + Must be a valid node. + @param [in] CallBack Callback function to call on each node. + @param [in, out] Context Void pointer used to pass some information + to the Callback function. + Optional, can be NULL. + @param [out] Status Optional parameter that can be used to get + the status of the Callback function. + If used, need to be init to EFI_SUCCESS. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +BOOLEAN +EFIAPI +AmlEnumTree ( + IN AML_NODE_HEADER * Node, + IN EDKII_AML_TREE_ENUM_CALLBACK CallBack, + IN OUT VOID * Context, OPTIONAL + OUT EFI_STATUS * Status OPTIONAL + ) +{ + BOOLEAN ContinueEnum; + + EAML_PARSE_INDEX Index; + EAML_PARSE_INDEX MaxIndex; + + LIST_ENTRY * StartLink; + LIST_ENTRY * CurrentLink; + + if (!IS_AML_NODE_VALID (Node) || (CallBack =3D=3D NULL)) { + ASSERT (0); + if (Status !=3D NULL) { + *Status =3D EFI_INVALID_PARAMETER; + } + return FALSE; + } + + ContinueEnum =3D (*CallBack)(Node, Context, Status); + if (ContinueEnum =3D=3D FALSE) { + return ContinueEnum; + } + + // Iterate through the fixed list of arguments. + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)Node + ); + for (Index =3D EAmlParseIndexTerm0; Index < MaxIndex; Index++) { + ContinueEnum =3D AmlEnumTree ( + AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index), + CallBack, + Context, + Status + ); + if (ContinueEnum =3D=3D FALSE) { + return ContinueEnum; + } + } + + // Iterate through the variable list of arguments. + StartLink =3D AmlNodeGetVariableArgList (Node); + if (StartLink !=3D NULL) { + CurrentLink =3D StartLink->ForwardLink; + while (CurrentLink !=3D StartLink) { + ContinueEnum =3D AmlEnumTree ( + (AML_NODE_HEADER*)CurrentLink, + CallBack, + Context, + Status + ); + if (ContinueEnum =3D=3D FALSE) { + return ContinueEnum; + } + CurrentLink =3D CurrentLink->ForwardLink; + } // while + } + + return ContinueEnum; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64084): https://edk2.groups.io/g/devel/message/64084 Mute This Topic: https://groups.io/mt/76149147/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64085+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245813764473.8232658887838; Wed, 12 Aug 2020 08:23:33 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id llP2YY1788612xTPpRK5OwpL; Wed, 12 Aug 2020 08:23:33 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.57]) by mx.groups.io with SMTP id smtpd.web10.17193.1597245808012342500 for ; Wed, 12 Aug 2020 08:23:28 -0700 X-Received: from AM5PR04CA0006.eurprd04.prod.outlook.com (2603:10a6:206:1::19) by VI1PR0802MB2287.eurprd08.prod.outlook.com (2603:10a6:800:9d::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.20; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com (2603:10a6:206:1:cafe::65) by AM5PR04CA0006.outlook.office365.com (2603:10a6:206:1::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:22 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64085+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT022.mail.protection.outlook.com (10.152.16.79) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:22 +0000 X-Received: ("Tessian outbound 7161e0c2a082:v64"); Wed, 12 Aug 2020 15:23:22 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 1ceccb5135ecf61b X-CR-MTA-TID: 64aa7808 X-Received: from 3af65b739352.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 210573BB-F326-49CF-9B74-033508B8DE82.1; Wed, 12 Aug 2020 15:23:16 +0000 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 3af65b739352.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:16 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NJZkfADO2TxBTZTa82TJQU09kOXbGubdKQLcOD08AuknQVpKlf+rx0LK3ZPiX3m+StJLyDKvbQKRDnmDiJISDXovsu6py6gAzuj1Je4L1l9FzudEoI0fMqgY0Y2td0kolnCAhGSg1KEpacVC518RO+GmU9vgDV0OhhbMVSjmmm3RAJ8z9IRfV3fz1xZaDdDUXuvVFEGCgcOqCbxR1rUhc8veN2k9I1+ExY3hPx4gpyjGnoEPLNE9Qo5h1OaKQN9qqUNy8fi419pE0GiJSPSbAXnA5VCT8AA6jmI2qewIOPMoXs0ivCRPjgpmPhTLK0WOdEsf24BSZe/ykvR8A4Zt6g== 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-SenderADCheck; bh=KDMkVFrjHfPT9uT53KbDc8FJ4HDcEz/dDynnkrf3wKg=; b=fnVLGHF/a7aEEefcCw1k/fHmvAHsjSFIWt2nMLeJov3jYJ0l2xC74prpAkasnVopR5TWzdWdXRznCq8rjKEVmrmxxIudykZE/fqKMEGfzPYntSAPAUVFyWM7UrHeN0JiXSYjUpVzjzcEiesGPe0puAN5nnCevk4KjFSJp1zNO69AgMSf1Ewrq+NgKGB45cg5j3oJnbsituTxtoxkkpRJsFBR1z3eb0dMUgpTyuWQBSsqMiz1XxSlraORcH4zWKt5CYz97qKlM8CpjAj2un+THWDg9CbDX1aeQOh/SGta1H1pjG2kAufsManKksWF+DKXx63RLRb4CIB2iYWmHe2fhQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB8PR06CA0027.eurprd06.prod.outlook.com (2603:10a6:10:100::40) by VI1PR08MB3456.eurprd08.prod.outlook.com (2603:10a6:803:7e::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:14 +0000 X-Received: from DB5EUR03FT035.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:100:cafe::21) by DB8PR06CA0027.outlook.office365.com (2603:10a6:10:100::40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:14 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT035.mail.protection.outlook.com (10.152.20.65) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:14 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:11 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:06 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:06 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 07/30] DynamicTablesPkg: AML tree traversal Date: Wed, 12 Aug 2020 16:22:13 +0100 Message-ID: <20200812152236.31164-8-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 329c66c0-367e-4dcc-978c-08d83ed3a64f X-MS-TrafficTypeDiagnostic: VI1PR08MB3456:|VI1PR0802MB2287: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:5236;OLM:5236; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: A1cNZU6VzjvDpdyaJbJS+TcaKIKxdcCW64q92I9r+j/fq/SCI6aSU0MpNE1/iFlKgJosIC0WM+0WRHrTSGry+W8jEvqv+MBCo8uhZAqKnGAkFVnoVTxM+ehyPvxllTqhf/kfhv7Wkxw4L/Uv43XYzkG1h6fXc3QZTl4fcb0n/iZ3dUmEo2QNwBmhkBue8WpyxiNgBqTcntfK26sFq0V05KkY3admejzlvTIMESfj+wJv073vVkV70OO8dQTvmK0yFgnkep+oofwJHq/o0SBu2Zitbd6f33/b7gtME0rmcJlRUvwS2eEQcsCNM7aHWm1ssWnjQyYsC4R8BR5ksNDowD5IMfC8ywPpcGm89qjeurgwpbmFfiXlcfTnucM+m7T5/l5zZu3Uwsm8i9wOROBk4w== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(396003)(39860400002)(346002)(376002)(136003)(46966005)(5660300002)(7696005)(426003)(478600001)(86362001)(44832011)(47076004)(36756003)(70586007)(1076003)(70206006)(54906003)(186003)(336012)(316002)(6666004)(26005)(19627235002)(2906002)(83380400001)(82310400002)(356005)(30864003)(6916009)(8936002)(2616005)(8676002)(4326008)(82740400003)(81166007);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB3456 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: d26f1a7c-f247-4b24-4177-08d83ed3a1bb X-Microsoft-Antispam-Message-Info: 9LnwAvFbclY6vTQJV2NI/CU+Kx5wUPVuwpj/DXI00676lpVTb5/LhLJXOk5XVOGoieAEheLqamRcmdZQIEczhFz4PIHeXgZ7zIS0YgzqthnKxpB/pXVShkEYbGfW2rCOfAXoCbD1tJi9z+hwhtgsed0Fiur7P1p0odWUFVp10gOdH4r2Ot8Rbl9SHEPDnNCwrjFLKCam19uT+IsMNMKtaCIZ+trCHQTCJRkumM9fa8BNOkT+xIlKkpH8diW7KsPPh7CQkBlVMrsLUwWikdHw6OLAvPYSqq5TR87EFCnxUx2Bhh+dh2T5eAk3ErHvJ3Tb3KzUoQQYVERyxSuQNnt1F8CJIzZ7YRJJsdAp15mPwW947yz7i/gXiPyXDeuu4zOgDVwYutUy2Z7qXcof2tKdQw== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:22.1401 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 329c66c0-367e-4dcc-978c-08d83ed3a64f 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: AM5EUR03FT022.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0802MB2287 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: jvn0pOv7mbQjxivhzzpdaxD7x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245813; bh=ygPJpWvSNHxWE/ACnFtCiJMHpgHtL2+3h2WpDlwKcew=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=YYaoIgTVsejTvW6uoVkJwY9ZpZf4dJSLaMQMTz8MY/3xRZHNQ91Qej0+Bu8xM062qV6 0JH/wtw4CK7hsvIszg52p0ItGWMDg1OkRemrHR4L8t5vywB07cwM4NiFZcmAJxJ2ImAY8 SuYF3Mw73p69IDLMYwMHjYyTuCmQvHScYTA= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML tree traversal provides interfaces to traverse the nodes in the AML tree. It provides interfaces to traverse the AML tree in the following order: - Traverse sibling nodes. (Node) /-i # Child of fixed argument b \ / |- [a][b][c][d] # Fixed Arguments |- {(e)->(f)->(g)} # Variable Arguments \ \-h # Child of variable argument e Traversal Order: - AmlGetNextSibling() : a, b, c, d, e, f, g, NULL - AmlGetPreviousSibling(): g, f, e, d, c, b, a, NULL - Iterate depth-first path (follow AML byte stream). (Node) /-i # Child of fixed argument b \ / |- [a][b][c][d] # Fixed Arguments |- {(e)->(f)->(g)} # Variable Arguments \ \-h # Child of variable argument e Traversal Order: - AmlGetNextNode(): a, b, i, c, d, e, h, f, g, NULL - AmlGetPreviousNode() g, f, h, e, d, c, i, b, a, NULL Note: The branch i and h will be traversed if it has any children. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c | 548 +++++= +++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h | 138 +++++ 2 files changed, 686 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c= b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c new file mode 100644 index 0000000000000000000000000000000000000000..9d0c794dbe773061233a4f88e18= cb55431bfbf4c --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c @@ -0,0 +1,548 @@ +/** @file + AML Tree Traversal. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include + +/** Get the sibling node among the nodes being in + the same variable argument list. + + (ParentNode) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(VarArgNode)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Node must be in a variable list of arguments. + Traversal Order: VarArgNode, f, g, NULL + + @ingroup CoreNavigationApis + + @param [in] VarArgNode Pointer to a node. + Must be in a variable list of arguments. + + @return The next node after VarArgNode in the variable list of arguments. + Return NULL if + - VarArgNode is the last node of the list, or + - VarArgNode is not part of a variable list of arguments. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetSiblingVariableArgument ( + IN AML_NODE_HEADER * VarArgNode + ) +{ + EAML_PARSE_INDEX Index; + AML_NODE_HEADER * ParentNode; + + // VarArgNode must be an object node or a data node, + // and be in a variable list of arguments. + if ((!IS_AML_OBJECT_NODE (VarArgNode) && + !IS_AML_DATA_NODE (VarArgNode)) || + AmlIsNodeFixedArgument (VarArgNode, &Index)) { + ASSERT (0); + return NULL; + } + + ParentNode =3D AmlGetParent (VarArgNode); + if (!IS_AML_NODE_VALID (ParentNode)) { + ASSERT (0); + return NULL; + } + + return AmlGetNextVariableArgument (ParentNode, VarArgNode); +} + +/** Get the next variable argument. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: e, f, g, NULL + + @param [in] Node Pointer to a Root node or Object Node. + @param [in] CurrVarArg Pointer to the Current Variable Argument. + + @return The node after the CurrVarArg in the variable list of arguments. + If CurrVarArg is NULL, return the first node of the + variable argument list. + Return NULL if + - CurrVarArg is the last node of the list, or + - Node does not have a variable list of arguments. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetNextVariableArgument ( + IN AML_NODE_HEADER * Node, + IN AML_NODE_HEADER * CurrVarArg + ) +{ + CONST LIST_ENTRY * StartLink; + CONST LIST_ENTRY * NextLink; + + // Node must be a RootNode or an Object Node + // and the CurrVarArg must not be a Root Node. + if ((!IS_AML_ROOT_NODE (Node) && + !IS_AML_OBJECT_NODE (Node)) || + ((CurrVarArg !=3D NULL) && + (!IS_AML_OBJECT_NODE (CurrVarArg) && + !IS_AML_DATA_NODE (CurrVarArg)))) { + ASSERT (0); + return NULL; + } + + StartLink =3D AmlNodeGetVariableArgList (Node); + if (StartLink =3D=3D NULL) { + return NULL; + } + + // Get the first child of the variable list of arguments. + if (CurrVarArg =3D=3D NULL) { + NextLink =3D StartLink->ForwardLink; + if (NextLink !=3D StartLink) { + return (AML_NODE_HEADER*)NextLink; + } + // List is empty. + return NULL; + } + + // Check if CurrVarArg is in the VariableArgument List. + if (!IsNodeInList (StartLink, &CurrVarArg->Link)) { + ASSERT (0); + return NULL; + } + + // Get the node following the CurrVarArg. + NextLink =3D CurrVarArg->Link.ForwardLink; + if (NextLink !=3D StartLink) { + return (AML_NODE_HEADER*)NextLink; + } + + // End of the list has been reached. + return NULL; +} + +/** Get the previous variable argument. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, e, NULL + + @param [in] Node Pointer to a root node or an object node. + @param [in] CurrVarArg Pointer to the Current Variable Argument. + + @return The node before the CurrVarArg in the variable list of + arguments. + If CurrVarArg is NULL, return the last node of the + variable list of arguments. + Return NULL if: + - CurrVarArg is the first node of the list, or + - Node doesn't have a variable list of arguments. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetPreviousVariableArgument ( + IN AML_NODE_HEADER * Node, + IN AML_NODE_HEADER * CurrVarArg + ) +{ + CONST LIST_ENTRY * StartLink; + CONST LIST_ENTRY * PreviousLink; + + // Node must be a RootNode or an Object Node + // and the CurrVarArg must not be a Root Node. + if ((!IS_AML_ROOT_NODE (Node) && + !IS_AML_OBJECT_NODE (Node)) || + ((CurrVarArg !=3D NULL) && + (!IS_AML_OBJECT_NODE (CurrVarArg) && + !IS_AML_DATA_NODE (CurrVarArg)))) { + ASSERT (0); + return NULL; + } + + StartLink =3D AmlNodeGetVariableArgList (Node); + if (StartLink =3D=3D NULL) { + return NULL; + } + + // Get the last child of the variable list of arguments. + if (CurrVarArg =3D=3D NULL) { + PreviousLink =3D StartLink->BackLink; + if (PreviousLink !=3D StartLink) { + return (AML_NODE_HEADER*)PreviousLink; + } + // List is empty. + return NULL; + } + + // Check if CurrVarArg is in the VariableArgument List. + if (!IsNodeInList (StartLink, &CurrVarArg->Link)) { + ASSERT (0); + return NULL; + } + + // Get the node before the CurrVarArg. + PreviousLink =3D CurrVarArg->Link.BackLink; + if (PreviousLink !=3D StartLink) { + return (AML_NODE_HEADER*)PreviousLink; + } + + // We have reached the beginning of the list. + return NULL; +} + +/** Get the next sibling node among the children of the input Node. + + This function traverses the FixedArguments followed by the + VariableArguments at the same level in the hierarchy. + + Fixed arguments are before variable arguments. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: a, b, c, d, e, f, g, NULL + + + @param [in] Node Pointer to a root node or an object node. + @param [in] ChildNode Get the node after the ChildNode. + + @return The node after the ChildNode among the children of the input Nod= e. + - If ChildNode is NULL, return the first available node among + the fixed argument list then variable list of arguments; + - If ChildNode is the last node of the fixed argument list, + return the first argument of the variable list of arguments; + - If ChildNode is the last node of the variable list of argumen= ts, + return NULL. + +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetNextSibling ( + IN CONST AML_NODE_HEADER * Node, + IN CONST AML_NODE_HEADER * ChildNode + ) +{ + EAML_PARSE_INDEX Index; + AML_NODE_HEADER * CandidateNode; + + // Node must be a RootNode or an Object Node + // and the CurrVarArg must not be a Root Node. + if ((!IS_AML_ROOT_NODE (Node) && + !IS_AML_OBJECT_NODE (Node)) || + ((ChildNode !=3D NULL) && + (!IS_AML_OBJECT_NODE (ChildNode) && + !IS_AML_DATA_NODE (ChildNode)))) { + ASSERT (0); + return NULL; + } + + if (IS_AML_OBJECT_NODE (Node)) { + if (ChildNode =3D=3D NULL) { + // Get the fixed argument at index 0 of the ChildNode. + CandidateNode =3D AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + EAmlParseIndexTerm0 + ); + if (CandidateNode !=3D NULL) { + return CandidateNode; + } + } else { + // (ChildNode !=3D NULL) + if (AmlIsNodeFixedArgument (ChildNode, &Index)) { + // Increment index to point to the next fixed argument. + Index++; + // The node is part of the list of fixed arguments. + if (Index =3D=3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)Node) + ) { + // It is at the last argument of the fixed argument list. + // Get the first argument of the variable list of arguments. + ChildNode =3D NULL; + } else { + // Else return the next node in the list of fixed arguments. + return AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index); + } + } + } + } // IS_AML_OBJECT_NODE (Node) + + // Else, get the next node in the variable list of arguments. + return AmlGetNextVariableArgument ( + (AML_NODE_HEADER*)Node, + (AML_NODE_HEADER*)ChildNode + ); +} + +/** Get the previous sibling node among the children of the input Node. + + This function traverses the FixedArguments followed by the + VariableArguments at the same level in the hierarchy. + + Fixed arguments are before variable arguments. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, e, d, c, b, a, NULL + + @param [in] Node The node to get the fixed argument from. + @param [in] ChildNode Get the node before the ChildNode. + + @return The node before the ChildNode among the children of the input No= de. + - If ChildNode is NULL, return the last available node among + the variable list of arguments then fixed argument list; + - If ChildNode is the first node of the variable list of argume= nts, + return the last argument of the fixed argument list; + - If ChildNode is the first node of the fixed argument list, + return NULL. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetPreviousSibling ( + IN CONST AML_NODE_HEADER * Node, + IN CONST AML_NODE_HEADER * ChildNode + ) +{ + EAML_PARSE_INDEX Index; + EAML_PARSE_INDEX MaxIndex; + + AML_NODE_HEADER * CandidateNode; + + // Node must be a Root Node or an Object Node + // and the ChildNode must not be a Root Node. + if ((!IS_AML_ROOT_NODE (Node) && + !IS_AML_OBJECT_NODE (Node)) || + ((ChildNode !=3D NULL) && + (!IS_AML_OBJECT_NODE (ChildNode) && + !IS_AML_DATA_NODE (ChildNode)))) { + ASSERT (0); + return NULL; + } + + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)Node + ); + + // Get the last variable argument if no ChildNode. + // Otherwise the fixed argument list is checked first. + if ((ChildNode !=3D NULL) && + IS_AML_OBJECT_NODE (Node) && + (MaxIndex !=3D EAmlParseIndexTerm0)) { + if (AmlIsNodeFixedArgument (ChildNode, &Index)) { + // The node is part of the list of fixed arguments. + if (Index =3D=3D EAmlParseIndexTerm0) { + // The node is the first fixed argument, return NULL. + return NULL; + } else { + // Return the previous node in the fixed argument list. + return AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + (EAML_PARSE_INDEX)(Index - 1) + ); + } + } + } + + // ChildNode is in the variable list of arguments. + CandidateNode =3D AmlGetPreviousVariableArgument ( + (AML_NODE_HEADER*)Node, + (AML_NODE_HEADER*)ChildNode + ); + if (CandidateNode !=3D NULL) { + if (!IS_AML_NODE_VALID (CandidateNode)) { + ASSERT (0); + return NULL; + } + // A Node has been found + return CandidateNode; + } else if (MaxIndex !=3D EAmlParseIndexTerm0) { + // ChildNode was the first node of the variable list of arguments. + return AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + (EAML_PARSE_INDEX)(MaxIndex - 1) + ); + } else { + // No fixed arguments or variable arguments. + return NULL; + } +} + +/** Iterate through the nodes in the same order as the AML bytestream. + + The iteration is similar to a depth-first path. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: a, b, i, c, d, e, h, f, g, NULL + Note: The branch i and h will be traversed if it has any children. + + @param [in] Node Pointer to a node. + + @return The next node in the AML bytestream order. + Return NULL if Node is the Node corresponding to the last + bytecode of the tree. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetNextNode ( + IN CONST AML_NODE_HEADER * Node + ) +{ + AML_NODE_HEADER * ParentNode; + AML_NODE_HEADER * CandidateNode; + + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return NULL; + } + + if (IS_AML_ROOT_NODE (Node) || IS_AML_OBJECT_NODE (Node)) { + // The node has children. Get the first child. + CandidateNode =3D AmlGetNextSibling (Node, NULL); + if (CandidateNode !=3D NULL) { + if (!IS_AML_NODE_VALID (CandidateNode)) { + ASSERT (0); + return NULL; + } + // A Node has been found + return CandidateNode; + } else if (IS_AML_ROOT_NODE (Node)) { + // The node is the root node and it doesn't have children. + return NULL; + } + } + + // We have traversed the current branch, go to the parent node + // and start traversing the next branch. + // Keep going up the tree until you reach the root node. + while (1) { + if (IS_AML_ROOT_NODE (Node)) { + // This is the last node of the tree. + return NULL; + } + + ParentNode =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (!IS_AML_NODE_VALID (ParentNode)) { + ASSERT (0); + return NULL; + } + + CandidateNode =3D AmlGetNextSibling (ParentNode, Node); + if (CandidateNode !=3D NULL) { + if (!IS_AML_NODE_VALID (CandidateNode)) { + ASSERT (0); + return NULL; + } + // A Node has been found + return CandidateNode; + } + + Node =3D ParentNode; + } // while + + return NULL; +} + +/** Iterate through the nodes in the reverse order of the AML bytestream. + + The iteration is similar to a depth-first path, + but done in a reverse order. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, h, e, d, c, i, b, a, NULL + Note: The branch i and h will be traversed if it has any children. + + @param [in] Node Pointer to a node. + + @return The previous node in the AML bytestream order. + Return NULL if Node is the Node corresponding to the last + bytecode of the tree. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetPreviousNode ( + IN CONST AML_NODE_HEADER * Node + ) +{ + AML_NODE_HEADER * ParentNode; + AML_NODE_HEADER * CandidateNode; + AML_NODE_HEADER * PreviousNode; + + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return NULL; + } + + while (1) { + + if (IS_AML_ROOT_NODE (Node)) { + // This is the root node. + return NULL; + } + + ParentNode =3D AmlGetParent ((AML_NODE_HEADER*)Node); + CandidateNode =3D AmlGetPreviousSibling (ParentNode, Node); + + if (CandidateNode =3D=3D NULL) { + // Node is the first child of its parent. + return ParentNode; + } else if (IS_AML_DATA_NODE (CandidateNode)) { + // CandidateNode is a data node, thus it has no children. + return CandidateNode; + } else if (IS_AML_OBJECT_NODE (CandidateNode)) { + // Get the previous node in the list of children of ParentNode, + // then get the last child of this node. + // If this node has children, get its last child, etc. + while (1) { + PreviousNode =3D CandidateNode; + CandidateNode =3D AmlGetPreviousSibling (PreviousNode, NULL); + if (CandidateNode =3D=3D NULL) { + return PreviousNode; + } else if (IS_AML_DATA_NODE (CandidateNode)) { + return CandidateNode; + } + } // while + + } else { + ASSERT (0); + return NULL; + } + } // while +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h= b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h new file mode 100644 index 0000000000000000000000000000000000000000..a4980b716d7542cd64d39094327= e21fa2f164a4c --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h @@ -0,0 +1,138 @@ +/** @file + AML Tree Traversal. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_TREE_TRAVERSAL_H_ +#define AML_TREE_TRAVERSAL_H_ + +#include + +/** Get the next sibling node among the children of the input Node. + + This function traverses the FixedArguments followed by the + VariableArguments at the same level in the hierarchy. + + Fixed arguments are before variable arguments. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: a, b, c, d, e, f, g, NULL + + + @param [in] Node Pointer to a root node or an object node. + @param [in] ChildNode Get the node after the ChildNode. + + @return The node after the ChildNode among the children of the input Nod= e. + - If ChildNode is NULL, return the first available node among + the fixed argument list then variable list of arguments; + - If ChildNode is the last node of the fixed argument list, + return the first argument of the variable list of arguments; + - If ChildNode is the last node of the variable list of argumen= ts, + return NULL. + +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetNextSibling ( + IN CONST AML_NODE_HEADER * Node, + IN CONST AML_NODE_HEADER * ChildNode + ); + +/** Get the previous sibling node among the children of the input Node. + + This function traverses the FixedArguments followed by the + VariableArguments at the same level in the hierarchy. + + Fixed arguments are before variable arguments. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, e, d, c, b, a, NULL + + @param [in] Node The node to get the fixed argument from. + @param [in] ChildNode Get the node before the ChildNode. + + @return The node before the ChildNode among the children of the input No= de. + - If ChildNode is NULL, return the last available node among + the variable list of arguments then fixed argument list; + - If ChildNode is the first node of the variable list of argume= nts, + return the last argument of the fixed argument list; + - If ChildNode is the first node of the fixed argument list, + return NULL. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetPreviousSibling ( + IN CONST AML_NODE_HEADER * Node, + IN CONST AML_NODE_HEADER * ChildNode + ); + +/** Iterate through the nodes in the same order as the AML bytestream. + + The iteration is similar to a depth-first path. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: a, b, i, c, d, e, h, f, g, NULL + Note: The branch i and h will be traversed if it has any children. + + @param [in] Node Pointer to a node. + + @return The next node in the AML bytestream order. + Return NULL if Node is the Node corresponding to the last + bytecode of the tree. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetNextNode ( + IN CONST AML_NODE_HEADER * Node + ); + +/** Iterate through the nodes in the reverse order of the AML bytestream. + + The iteration is similar to a depth-first path, + but done in a reverse order. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, h, e, d, c, i, b, a, NULL + Note: The branch i and h will be traversed if it has any children. + + @param [in] Node Pointer to a node. + + @return The previous node in the AML bytestream order. + Return NULL if Node is the Node corresponding to the last + bytecode of the tree. +**/ +AML_NODE_HEADER * +EFIAPI +AmlGetPreviousNode ( + IN CONST AML_NODE_HEADER * Node + ); + +#endif // AML_TREE_TRAVERSAL_H_ + --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64085): https://edk2.groups.io/g/devel/message/64085 Mute This Topic: https://groups.io/mt/76149149/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64087+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245817271839.2864223374473; Wed, 12 Aug 2020 08:23:37 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 4wg5YY1788612x1QDfL88u3V; Wed, 12 Aug 2020 08:23:35 -0700 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com (EUR05-VI1-obe.outbound.protection.outlook.com [40.107.21.49]) by mx.groups.io with SMTP id smtpd.web12.16973.1597245813069188506 for ; Wed, 12 Aug 2020 08:23:33 -0700 X-Received: from AM6PR10CA0096.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::37) by DB8PR08MB5052.eurprd08.prod.outlook.com (2603:10a6:10:e8::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:29 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::31) by AM6PR10CA0096.outlook.office365.com (2603:10a6:209:8c::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:29 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64087+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:29 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:29 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: b82a804e057189ba X-CR-MTA-TID: 64aa7808 X-Received: from 5ee88d692784.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 269F87EB-DF38-4B3B-8A59-6A8E603FCA82.1; Wed, 12 Aug 2020 15:23:20 +0000 X-Received: from EUR02-AM5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 5ee88d692784.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:20 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lH5Axk7ZHJYn/jMiL5xFw/vvKZcyNdAmxN9Dyen/9zJlXJkYLprCPc30pVO675RjPoaZo98j/G2Q/eLh7kMVCzZA7ldK7TQHjgduEEcdITKTsIC3+EO5A+W4u/mrmuU9sYbizeKZsMhhiHq5AC54E6lbFSlVgRg6mO2kG78dnduBpms+k5kXfFK81cw281m0TPF6EH0Ya4m6QM4nSv+Sr/3N3nA6TkXepcS7y6BZxP1RNpMnObq/43cJBFWzs8PuAOPzu77c6HqJU0E660KtbB6ToinxiPTVPXBdiPx1qi4AhYPC8Ll7zOcnFsu555kxfyHPI0DsYCpPYaTR+qu4Cg== 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-SenderADCheck; bh=4DMIZmYcUdd++dhTIL7D+8tHfIQFSNsMUCjQZJQSOWY=; b=IK8vhlUU2+t0pK/93d6wFEdLpQPTrRvCD913TVdClQu2d6hzyXw3TVdaFqLz0p6d4e29DAppBN2qNlbrQaMqrcarNFinwuqIPlFKXuhOW/cNijX8YO8g1PKbNdaS6ehy9wEhELoSYAgpFzpQ+cMMgTEyYWiYbvx+fJxI8KUBijjdZhhjX9SDL2lS/0B6GqPVWjRJzSu3KIwLfYhsmQSXr0fvhzbNIOZWfkdNUK0FDICWldyY7Yb9gLGsSvAov02qOvlmIQzn8FZFb8m7NuY7kcZvf8RLyVr+p1YiqliN305VYTFDGrsWvJxSoz1WjzViwEWJNW8WGozHFhxZVp3SvA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6P193CA0014.EURP193.PROD.OUTLOOK.COM (2603:10a6:6:29::24) by AM8PR08MB5682.eurprd08.prod.outlook.com (2603:10a6:20b:1c5::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:19 +0000 X-Received: from DB5EUR03FT018.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:29:cafe::e4) by DB6P193CA0014.outlook.office365.com (2603:10a6:6:29::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:19 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT018.mail.protection.outlook.com (10.152.20.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:17 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:11 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:10 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 08/30] DynamicTablesPkg: AML tree iterator Date: Wed, 12 Aug 2020 16:22:14 +0100 Message-ID: <20200812152236.31164-9-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bff83bee-5dbb-4873-f763-08d83ed3aa8b X-MS-TrafficTypeDiagnostic: AM8PR08MB5682:|DB8PR08MB5052: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:5516;OLM:5516; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: Rc8czPMOfmEiGfdE5x2CRNrHjKgA9SZFwAayruh5fmDHTsa/qxawyDA41jbeu1wZbCFHRiqNjrcZH61YpeyCzg3Ki2NkaIBraONuyGSVYDJ6E0xUOwCCL/Q2qN/jv7I+++emwvr0H/QJ5Zz4El3Mlr4jAE/578KBh4Og5s+dQMf3nZPUYy6/+J3BwQsStH7v8K4+aenD/z8oHmZ5WV3M26AVYPcP0Cr+LAfu7+282aAokm6G6+4scsAuDWrrMJ5CvcKqSyGqL7PvdzS7NOcpBh4/KbZZ2I/RSCv7ktVaXNgJKj5VgEHQLiT9z2tfcjCS1jyeBtwF87JBSzREceml2Ff5Gc77LUZ1Ubs8tH3nqYw/9iplBtVBqt0iJx0H7tMcaPmnlogBo7OtMi3S90vB9A== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(376002)(346002)(39860400002)(396003)(136003)(46966005)(36756003)(8676002)(478600001)(86362001)(2906002)(2616005)(426003)(44832011)(6916009)(83380400001)(47076004)(316002)(356005)(4326008)(26005)(54906003)(7696005)(8936002)(1076003)(186003)(5660300002)(70206006)(82310400002)(30864003)(81166007)(70586007)(336012)(82740400003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR08MB5682 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 5a2b4105-4149-4337-c4df-08d83ed3a39e X-Microsoft-Antispam-Message-Info: FzKoHmasEIu/hU/WLZa8bBTppmgySFTUzVVZIQTQN61/TzVnsOfPTRDooFOwU1iDzJ2fm+AHqCD+esLZwpjDQAO5eM3J1tbdsPs7PPwfKs0qu1sPDgMEuZABbZEDNnfPUtupk60PlhIb6x2+daOw9PomXEdjr9qKZt3KQAO3dJ1452LQkvy1eKEmGAg3zYnGwMSivrFH08TNfDzUdu1i5DRPNhXaxgyA+9QaDpw0CfYSrbzbl7NRoLVF0N3HtRntY9rf0lHLghyrkhbJ2dIUm/Jy6lcd97gUBV5U6HyXsvJAOsHCZrCkbsc5TCyC73grdGwiZ2266qLv1fAr9pBMb1NCB08EafaE3U35XhY1LD2cllG4E30idj2GmMKg+BTOCmeeWIx+U7JW9wMKAtprSg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:29.2476 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bff83bee-5dbb-4873-f763-08d83ed3aa8b 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: AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB5052 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 3vrkppqoeIHjIOhB2ufxvYnOx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245815; bh=rJixN0p+4rvhnjOpYRNYyHY21/Z9sVLY3bXhPEKaMwU=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=nseckfnmx+nlEq178iCt2L3gYtZ1OpftEU0eDmr7xkgUmAotd6XTursPe3eeUAk3tZd lddxZUgfcOK88Oo3XFTgqAfxtnbWtumGKDwxDlS/d3NqLSFltYMDz5GGL4+9wpaKnlUdz 4GfVbReW9i8p0ccJmt7KU/X+OGTscrnkZFI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML tree iterator provides interfaces to traverse the nodes in the AML tree. The iterator can traverse the AML tree nodes in the following order: - Linear progression: Iterate following the AML byte stream order (depth first). - Branch progression: Iterate following the AML byte stream order (depth first), but stop iterating at the end of the branch. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c | 353 ++++++= ++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h | 220 ++++++= ++++++ 2 files changed, 573 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c = b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c new file mode 100644 index 0000000000000000000000000000000000000000..e99c234990c669c89767d922aad= 75627adb2c350 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c @@ -0,0 +1,353 @@ +/** @file + AML Tree Iterator. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include + +#include +#include + +/** Iterator to traverse the tree. + + This is an internal structure. +*/ +typedef struct AmlTreeInternalIterator { + /// External iterator structure, containing the external APIs. + /// Must be the first field. + AML_TREE_ITERATOR Iterator; + + // Note: The following members of this structure are opaque to the users + // of the Tree iterator APIs. + + /// Pointer to the node on which the iterator has been initialized. + CONST AML_NODE_HEADER * InitialNode; + + /// Pointer to the current node. + CONST AML_NODE_HEADER * CurrentNode; + + /// Iteration mode. + /// Allow to choose how to traverse the tree/choose which node is next. + EAML_ITERATOR_MODE Mode; +} AML_TREE_ITERATOR_INTERNAL; + +/** Get the current node of an iterator. + + @param [in] Iterator Pointer to an iterator. + @param [out] OutNode Pointer holding the current node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlIteratorGetNode ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HEADER ** OutNode + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)Iterator; + + // CurrentNode can be NULL, but InitialNode cannot. + if ((OutNode =3D=3D NULL) || + (InternalIterator =3D=3D NULL) || + (InternalIterator->Mode <=3D EAmlIteratorUnknown) || + (InternalIterator->Mode >=3D EAmlIteratorModeMax) || + !IS_AML_NODE_VALID (InternalIterator->InitialNode) || + ((InternalIterator->CurrentNode !=3D NULL) && + !IS_AML_NODE_VALID (InternalIterator->CurrentNode))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutNode =3D (AML_NODE_HEADER*)InternalIterator->CurrentNode; + + return EFI_SUCCESS; +} + +/** Move the current node of the iterator to the next node, + according to the iteration mode selected. + + If NextNode is not NULL, return the next node. + + @param [in] Iterator Pointer to an iterator. + @param [out] NextNode If not NULL, updated to the next node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlIteratorGetNextLinear ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HEADER ** NextNode + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)Iterator; + + // CurrentNode can be NULL, but InitialNode cannot. + if ((InternalIterator =3D=3D NULL) || + (InternalIterator->Mode !=3D EAmlIteratorLinear) || + !IS_AML_NODE_VALID (InternalIterator->InitialNode) || + !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the next node according to the iteration mode. + InternalIterator->CurrentNode =3D AmlGetNextNode ( + InternalIterator->CurrentNode + ); + + if (NextNode !=3D NULL) { + *NextNode =3D (AML_NODE_HEADER*)InternalIterator->CurrentNode; + } + return EFI_SUCCESS; +} + +/** Move the current node of the iterator to the previous node, + according to the iteration mode selected. + + If PrevNode is not NULL, return the previous node. + + @param [in] Iterator Pointer to an iterator. + @param [out] PrevNode If not NULL, updated to the previous node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlIteratorGetPreviousLinear ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HEADER ** PrevNode + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)Iterator; + + // CurrentNode can be NULL, but InitialNode cannot. + if ((InternalIterator =3D=3D NULL) || + (InternalIterator->Mode !=3D EAmlIteratorLinear) || + !IS_AML_NODE_VALID (InternalIterator->InitialNode) || + !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the previous node according to the iteration mode. + InternalIterator->CurrentNode =3D AmlGetPreviousNode ( + InternalIterator->CurrentNode + ); + if (PrevNode !=3D NULL) { + *PrevNode =3D (AML_NODE_HEADER*)InternalIterator->CurrentNode; + } + return EFI_SUCCESS; +} + +/** Move the current node of the iterator to the next node, + according to the iteration mode selected. + + If NextNode is not NULL, return the next node. + + @param [in] Iterator Pointer to an iterator. + @param [out] NextNode If not NULL, updated to the next node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlIteratorGetNextBranch ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HEADER ** NextNode + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + AML_NODE_HEADER * Node; + + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)Iterator; + + // CurrentNode can be NULL, but InitialNode cannot. + if ((InternalIterator =3D=3D NULL) || + (InternalIterator->Mode !=3D EAmlIteratorBranch) || + !IS_AML_NODE_VALID (InternalIterator->InitialNode) || + !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Node =3D AmlGetNextNode (InternalIterator->CurrentNode); + // Check whether NextNode is a sibling of InitialNode. + if (AmlGetParent (Node) =3D=3D + AmlGetParent ((AML_NODE_HEADER*)InternalIterator->InitialNode)) { + Node =3D NULL; + } + + InternalIterator->CurrentNode =3D Node; + + if (NextNode !=3D NULL) { + *NextNode =3D Node; + } + return EFI_SUCCESS; +} + +/** Move the current node of the iterator to the previous node, + according to the iteration mode selected. + + If PrevNode is not NULL, return the previous node. + + @param [in] Iterator Pointer to an iterator. + @param [out] PrevNode If not NULL, updated to the previous node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlIteratorGetPreviousBranch ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HEADER ** PrevNode + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + AML_NODE_HEADER * Node; + + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)Iterator; + + // CurrentNode can be NULL, but InitialNode cannot. + if ((InternalIterator =3D=3D NULL) || + (InternalIterator->Mode !=3D EAmlIteratorBranch) || + !IS_AML_NODE_VALID (InternalIterator->InitialNode) || + !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Node =3D AmlGetPreviousNode (InternalIterator->CurrentNode); + // Check whether PreviousNode is a sibling of InitialNode. + if (AmlGetParent (Node) =3D=3D + AmlGetParent ((AML_NODE_HEADER*)InternalIterator->InitialNode)) { + Node =3D NULL; + } + + InternalIterator->CurrentNode =3D Node; + + if (PrevNode !=3D NULL) { + *PrevNode =3D Node; + } + return EFI_SUCCESS; +} + +/** Initialize an iterator. + + Note: The caller must call AmlDeleteIterator () to free the memory + allocated for the iterator. + + @param [in] Node Pointer to the node. + @param [in] IteratorMode Selected mode to traverse the tree. + @param [out] IteratorPtr Pointer holding the created iterator. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlInitializeIterator ( + IN AML_NODE_HEADER * Node, + IN EAML_ITERATOR_MODE IteratorMode, + OUT AML_TREE_ITERATOR ** IteratorPtr + ) +{ + AML_TREE_ITERATOR_INTERNAL * InternalIterator; + + if (!IS_AML_NODE_VALID (Node) || + (IteratorMode <=3D EAmlIteratorUnknown) || + (IteratorMode >=3D EAmlIteratorModeMax) || + (IteratorPtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *IteratorPtr =3D NULL; + InternalIterator =3D (AML_TREE_ITERATOR_INTERNAL*)AllocateZeroPool ( + sizeof ( + AML_TREE_ITERATOR_IN= TERNAL + ) + ); + if (InternalIterator =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + InternalIterator->InitialNode =3D Node; + InternalIterator->CurrentNode =3D Node; + InternalIterator->Mode =3D IteratorMode; + InternalIterator->Iterator.GetNode =3D AmlIteratorGetNode; + + switch (InternalIterator->Mode) { + case EAmlIteratorLinear: + { + InternalIterator->Iterator.GetNext =3D AmlIteratorGetNextLinear; + InternalIterator->Iterator.GetPrevious =3D AmlIteratorGetPreviousLin= ear; + break; + } + case EAmlIteratorBranch: + { + InternalIterator->Iterator.GetNext =3D AmlIteratorGetNextBranch; + InternalIterator->Iterator.GetPrevious =3D AmlIteratorGetPreviousBra= nch; + break; + } + default: + { + ASSERT (0); + FreePool (InternalIterator); + return EFI_INVALID_PARAMETER; + } + } // switch + + *IteratorPtr =3D &InternalIterator->Iterator; + + return EFI_SUCCESS; +} + +/** Delete an iterator. + + Note: The caller must have first initialized the iterator with the + AmlInitializeIterator () function. + + @param [in] Iterator Pointer to an iterator. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteIterator ( + IN AML_TREE_ITERATOR * Iterator + ) +{ + if (Iterator =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (Iterator); + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h = b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h new file mode 100644 index 0000000000000000000000000000000000000000..d96eecab916818ceb0ab46a25e5= 151916cd4451d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h @@ -0,0 +1,220 @@ +/** @file + AML Iterator. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_ITERATOR_H_ +#define AML_ITERATOR_H_ + +/* This header file does not include internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions + must be included by the caller file. The function prototypes must + only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node + definitions. + This allows to keep the functions defined here both internal and + potentially external. If necessary, any function of this file can + be exposed externally. + The Api folder is internal to the AmlLib, but should only use these + functions. They provide a "safe" way to interact with the AmlLib. +*/ + +/** + @defgroup IteratorLibrary Iterator library + @ingroup NavigationApis + @{ + The iterator library allow to navigate in the AML tree using an iterat= or. + It is possible to initialize/delete an iterator. + + This iterator can progress in the tree by different orders: + - Linear progression: Iterate following the AML bytestream order + (depth first). + - Branch progression: Iterate following the AML bytestream order + (depth first), but stop iterating at the + end of the branch. + + An iterator has the following features: + - GetNode: Get the current node pointed by the iterator. + - GetNext: Move the current node of the iterator to the next + node, according to the iteration mode selected. + - GetPrevious: Move the current node of the iterator to the previous + node, according to the iteration mode selected. + @} +*/ + +/** + @defgroup IteratorApis Iterator APIs + @ingroup IteratorLibrary + @{ + Iterator APIs defines the action that can be done on an iterator: + - Initialization; + - Deletion; + - Getting the node currently pointed by the iterator; + - Moving to the next node; + - Moving to the previous node. + @} +*/ + +/** + @defgroup IteratorStructures Iterator structures + @ingroup IteratorLibrary + @{ + Iterator structures define the enum/define values and structures relat= ed + to iterators. + @} +*/ + +/** Iterator mode. + + Modes to choose how the iterator is progressing in the tree. + A + \-B <- Iterator initialized with this node. + | \-C + | | \-D + | \-E + | \-F + | \-G + \-H + \-I + + @ingroup IteratorStructures +*/ +typedef enum EAmlIteratorMode { + EAmlIteratorUnknown, ///< Unknown/Invalid AML IteratorMode + EAmlIteratorLinear, ///< Iterate following the AML bytestream or= der + /// (depth first). + /// The order followed by the iterator woul= d be: + /// B, C, D, E, F, G, H, I, NULL. + EAmlIteratorBranch, ///< Iterate through the node of a branch. + /// The iteration follows the AML bytestream + /// order but within the branch B. + /// The order followed by the iterator woul= d be: + /// B, C, D, E, F, G, NULL. + EAmlIteratorModeMax ///< Max enum. +} EAML_ITERATOR_MODE; + +/** Iterator. + + Allows to traverse the tree in different orders. + + @ingroup IteratorStructures +*/ +typedef struct AmlTreeIterator AML_TREE_ITERATOR; + +/** Function pointer to a get the current node of the iterator. + + @ingroup IteratorApis + + @param [in] Iterator Pointer to an iterator. + @param [out] OutNode Pointer holding the current node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +*/ +typedef +EFI_STATUS +(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_NODE) ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HANDLE * OutNode + ); + +/** Function pointer to move the current node of the iterator to the + next node, according to the iteration mode selected. + + If NextNode is not NULL, return the next node. + + @ingroup IteratorApis + + @param [in] Iterator Pointer to an iterator. + @param [out] NextNode If not NULL, updated to the next node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +*/ +typedef +EFI_STATUS +(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_NEXT) ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HANDLE * NextNode + ); + +/** Function pointer to move the current node of the iterator to the + previous node, according to the iteration mode selected. + + If PrevNode is not NULL, return the previous node. + + @ingroup IteratorApis + + @param [in] Iterator Pointer to an iterator. + @param [out] PrevNode If not NULL, updated to the previous node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +*/ +typedef +EFI_STATUS +(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_PREVIOUS) ( + IN AML_TREE_ITERATOR * Iterator, + OUT AML_NODE_HANDLE * PrevNode + ); + +/** Iterator structure to traverse the tree. + + @ingroup IteratorStructures +*/ +typedef struct AmlTreeIterator { + /// Get the current node of the iterator. + EDKII_AML_TREE_ITERATOR_GET_NODE GetNode; + + /// Update the current node of the iterator with the next node. + EDKII_AML_TREE_ITERATOR_GET_NEXT GetNext; + + /// Update the current node of the iterator with the previous node. + EDKII_AML_TREE_ITERATOR_GET_PREVIOUS GetPrevious; +} AML_TREE_ITERATOR; + + +/** Initialize an iterator. + + Note: The caller must call AmlDeleteIterator () to free the memory + allocated for the iterator. + + @ingroup IteratorApis + + @param [in] Node Pointer to the node. + @param [in] IteratorMode Selected mode to traverse the tree. + @param [out] IteratorPtr Pointer holding the created iterator. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlInitializeIterator ( + IN AML_NODE_HANDLE Node, + IN EAML_ITERATOR_MODE IteratorMode, + OUT AML_TREE_ITERATOR ** IteratorPtr + ); + +/** Delete an iterator. + + Note: The caller must have first initialized the iterator with the + AmlInitializeIterator () function. + + @ingroup IteratorApis + + @param [in] Iterator Pointer to an iterator. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteIterator ( + IN AML_TREE_ITERATOR * Iterator + ); + +#endif // AML_ITERATOR_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64087): https://edk2.groups.io/g/devel/message/64087 Mute This Topic: https://groups.io/mt/76149155/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64086+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245813673391.8253211500064; Wed, 12 Aug 2020 08:23:33 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id c9t4YY1788612xk9vCQ7oApA; Wed, 12 Aug 2020 08:23:33 -0700 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com (EUR04-DB3-obe.outbound.protection.outlook.com [40.107.6.47]) by mx.groups.io with SMTP id smtpd.web11.17173.1597245811724916422 for ; Wed, 12 Aug 2020 08:23:32 -0700 X-Received: from AM5PR0402CA0006.eurprd04.prod.outlook.com (2603:10a6:203:90::16) by DB6PR0801MB1814.eurprd08.prod.outlook.com (2603:10a6:4:37::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:27 +0000 X-Received: from AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:90:cafe::3f) by AM5PR0402CA0006.outlook.office365.com (2603:10a6:203:90::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:27 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64086+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT046.mail.protection.outlook.com (10.152.16.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:27 +0000 X-Received: ("Tessian outbound 7fc8f57bdedc:v64"); Wed, 12 Aug 2020 15:23:27 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: d4c6dfcc73d5f20a X-CR-MTA-TID: 64aa7808 X-Received: from b2429d5f0b3b.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 59A822B1-62C7-4390-93BD-4EF69C996C06.1; Wed, 12 Aug 2020 15:23:21 +0000 X-Received: from EUR01-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id b2429d5f0b3b.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:21 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=J18t6Yrvoz4kgtYaIC0TAYeMwmrI5q2wZhbyXiJmnCVMIMK1nLof4571wECMrkRErZrXoM2pTK8pDJUyNUHkMpyEa5tn2FRFoTyRakdsPtEtCP0jN9xx54CFR8R+S1cwEyWK2oRjiV06uPCaNpp3DjMhVOIPjlNeY4bwrY+dWuP2sPu7r2zp3qQiY5AWvUCHJx33zqh7tpKQbO/AutxyavH4jatbJ94hEp2BbCYw0qrn10Di7vxk0aQ2dFLFW3e5TU9oQit/dsupWs+QhqecNW61isduNlVAbp6tZ1lUjd18eKRov6GDrwFHbFvX9KFvea6rIi2zZefJHsMCPH/pJg== 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-SenderADCheck; bh=lgM06d5++WXsRBIacWXq6dkxI50dnmIgll9skX0vVEk=; b=Ff3fCWbf3k9uCr5K8+BEQVFtfElGr4+IqT0GY1qQHl74KuYvZJosY52PA1YRQaaeqKcInBTLj1fFQb3u6oPPIjWT6pKLbgBFVooPo8Jagc4y81ld42lL3zNk6Dlt6w/n4goz0rSqtz2ThFEI5kTadqFuYXkIEYnwKb/48rKT2Z6Z4IGbsteVFv97tVQO5QxVCWj1wVwqd6X+38TQ3o4Hs4ZWM/K8G0T+gjaJTo35mgHES9Ru8vYJasHkpJnW2wcF3w0j4QuoZAelCQqTV4M7KIkryWB/kxDuBL7siX0CH2bzeB3b8kp0IiK623rRDaWeiuu75VL0DWACnhoghmh7Zg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6P193CA0011.EURP193.PROD.OUTLOOK.COM (2603:10a6:6:29::21) by VE1PR08MB4877.eurprd08.prod.outlook.com (2603:10a6:802:a4::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:20 +0000 X-Received: from DB5EUR03FT018.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:29:cafe::e5) by DB6P193CA0011.outlook.office365.com (2603:10a6:6:29::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:20 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT018.mail.protection.outlook.com (10.152.20.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:20 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:15 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:14 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 09/30] DynamicTablesPkg: AML tree/node cloning Date: Wed, 12 Aug 2020 16:22:15 +0100 Message-ID: <20200812152236.31164-10-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f02b1e68-cae1-48b2-41bb-08d83ed3a949 X-MS-TrafficTypeDiagnostic: VE1PR08MB4877:|DB6PR0801MB1814: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:6108;OLM:6108; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: 5H1WQA6YmUDlblxbbdzWCYtyCkBUdQN7dFDWcPnw0rytMdYinXAM8SnWK3jcaZDFP0nYBylooejpC3N/4A2erJLowYTZ8NyA2xOaicn+RE+9deZK30wJZGgbId15Wa228djKrY02ST6NX5UJuB5ie/Nd+D2gu0bLarTNrWVChp5CPnmMlQVuN5UcjhQ8RtaLd3sFpk/D5WBGdUxAltRsxvzsy8oUdRYc9qPAsXQgVLHs3BpIx9QHK5QpPbbTC/YDxkL/P49JWFurGD1g5f6zpBywH6TO03UWyiSvn+UUbFatBfsewyFufvoZug1aF7aXG4dd12SI39ks0rxvstb0290ZWKi/NItg78c/Ue3bv9ej4Gi9wwoTO1KunkLZKtx4d8C8XmR2o8HY484I1ofjDQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(39860400002)(136003)(376002)(346002)(396003)(46966005)(4326008)(8676002)(2906002)(82740400003)(356005)(6916009)(81166007)(47076004)(316002)(478600001)(5660300002)(54906003)(186003)(26005)(44832011)(83380400001)(336012)(70206006)(7696005)(70586007)(8936002)(82310400002)(2616005)(426003)(86362001)(36756003)(1076003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR08MB4877 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: cbe0c1d6-fcf8-47f9-84b3-08d83ed3a501 X-Microsoft-Antispam-Message-Info: hx2WI2l0aXsqCHMXmnxDtflN8re0pz9u4h3SJ86tT5h85mSn1pAS9cGsQrRq1YgHdwit9kGjtzWm04eggeqPffi+oC36rAFN/Ed/hAbdmlVIRB0tp9hgochBDaGOBpipQ9h7mGc7TgtNHYBrw68ZhGNsQlyrrkJZjKtDj6HcM3dw+le1nqYtEOWR+zXiI68r0U7KqbStAnwnPP/PVCYxkVkJYp6oUgzs6qK/73IoV7C3GG1vk03CNDejbTVQR6sXnpDYOmytqVIk9oI7SQRlDKSZQnEBlmURNp4ASat91Cgj+GsAlxCUaLBW8uQfPYUQZw76Ma0Ffr3QjRf7yGwdgAgC2hcaFqM7DPYiteuoariFdRHp21BAY2fXlK1NA8gBWjWU6vG73XZROQBoQjps/A== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:27.1527 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f02b1e68-cae1-48b2-41bb-08d83ed3a949 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: AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1814 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 9ybtNK7PHoWIzhWiob9tYLADx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245813; bh=qaKkiNSWerP3DFbR/rExuUmN4WMLLWqZ9G9vU2TaUbQ=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=iUL35xQlMIcVqPxjuZTonPlUWAsBKP6RZ7Y8CKy+tqZQI1IT5vfrruVNqaAU0RSggmd +170GUYTdOmtmCX9siFVOV0/ct2FxqfNlK5V2DNw/UMd5RNC2uMwBHmWdIlHZFvquak2+ Ndm7gYy6tupuHE3QMLq8tEiGrfaZ0wTSee8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois It is often desirable to clone an AML branch/tree or an AML node. An example of could be to clone an AML template before fixup so that the original AML template remains unmodified. Another example would be replicating a device branch in the AML tree and fixing up the device information. To facilitate such scenarios the AmlLib library provides functions that can be used to clone an AML branch/tree or an AML node. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c | 205 +++++++++++++= +++++++ 1 file changed, 205 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c b/Dynam= icTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c new file mode 100644 index 0000000000000000000000000000000000000000..e09372b039f1f232de500effae7= d403d56c989cd --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c @@ -0,0 +1,205 @@ +/** @file + AML Clone. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include + +/** Clone a node. + + This function does not clone the children nodes. + The cloned node returned is not attached to any tree. + + @param [in] Node Pointer to a node. + @param [out] ClonedNode Pointer holding the cloned node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCloneNode ( + IN AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** ClonedNode + ) +{ + EFI_STATUS Status; + + AML_OBJECT_NODE * ObjectNode; + AML_DATA_NODE * DataNode; + AML_ROOT_NODE * RootNode; + + if (!IS_AML_NODE_VALID (Node) || + (ClonedNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *ClonedNode =3D NULL; + + if (IS_AML_DATA_NODE (Node)) { + DataNode =3D (AML_DATA_NODE*)Node; + Status =3D AmlCreateDataNode ( + DataNode->DataType, + DataNode->Buffer, + DataNode->Size, + (AML_DATA_NODE**)ClonedNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } else if (IS_AML_OBJECT_NODE (Node)) { + ObjectNode =3D (AML_OBJECT_NODE*)Node; + + Status =3D AmlCreateObjectNode ( + ObjectNode->AmlByteEncoding, + ObjectNode->PkgLen, + (AML_OBJECT_NODE**)ClonedNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } else if (IS_AML_ROOT_NODE (Node)) { + RootNode =3D (AML_ROOT_NODE*)Node; + + Status =3D AmlCreateRootNode ( + RootNode->SdtHeader, + (AML_ROOT_NODE**)ClonedNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** Clone a node and its children (clone a tree branch). + + The cloned branch returned is not attached to any tree. + + @param [in] Node Pointer to a node. + Node is the head of the branch to clone. + @param [out] ClonedNode Pointer holding the head of the created cloned + branch. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCloneTree ( + IN AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** ClonedNode + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * HeadNode; + AML_NODE_HEADER * ClonedChildNode; + AML_NODE_HEADER * FixedArgNode; + + EAML_PARSE_INDEX Index; + EAML_PARSE_INDEX MaxIndex; + + LIST_ENTRY * StartLink; + LIST_ENTRY * CurrentLink; + + if (!IS_AML_NODE_VALID (Node) || + (ClonedNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCloneNode (Node, &HeadNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Clone the fixed arguments and bind them to their parent. + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)Node + ); + for (Index =3D EAmlParseIndexTerm0; Index < MaxIndex; Index++) { + FixedArgNode =3D AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index); + if (FixedArgNode =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + ASSERT (0); + goto error_handler; + } + + // Clone child. + Status =3D AmlCloneTree ( + FixedArgNode, + &ClonedChildNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Bind child. + Status =3D AmlSetFixedArgument ( + (AML_OBJECT_NODE*)HeadNode, + Index, + ClonedChildNode + ); + if (EFI_ERROR (Status)) { + AmlDeleteTree (ClonedChildNode); + ASSERT (0); + goto error_handler; + } + } // for + + // Clone the variable arguments and bind them to their parent. + StartLink =3D AmlNodeGetVariableArgList (Node); + if (StartLink !=3D NULL) { + CurrentLink =3D StartLink->ForwardLink; + while (CurrentLink !=3D StartLink) { + // Clone child. + Status =3D AmlCloneTree ((AML_NODE_HEADER*)CurrentLink, &ClonedChild= Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Bind child. + Status =3D AmlVarListAddTailInternal ( + HeadNode, + ClonedChildNode + ); + if (EFI_ERROR (Status)) { + AmlDeleteTree (ClonedChildNode); + ASSERT (0); + goto error_handler; + } + + CurrentLink =3D CurrentLink->ForwardLink; + } // while + } + + *ClonedNode =3D HeadNode; + return Status; + +error_handler: + *ClonedNode =3D NULL; + + if (HeadNode !=3D NULL) { + AmlDeleteTree (HeadNode); + } + + return Status; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64086): https://edk2.groups.io/g/devel/message/64086 Mute This Topic: https://groups.io/mt/76149154/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64088+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245818460181.1705231086661; Wed, 12 Aug 2020 08:23:38 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id K1fFYY1788612xgY0BNsZdyH; Wed, 12 Aug 2020 08:23:37 -0700 X-Received: from EUR03-DB5-obe.outbound.protection.outlook.com (EUR03-DB5-obe.outbound.protection.outlook.com [40.107.4.41]) by mx.groups.io with SMTP id smtpd.web11.17174.1597245813542456829 for ; Wed, 12 Aug 2020 08:23:34 -0700 X-Received: from AM6P193CA0124.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::29) by VI1PR08MB3357.eurprd08.prod.outlook.com (2603:10a6:803:45::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:29 +0000 X-Received: from VE1EUR03FT056.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:85:cafe::9d) by AM6P193CA0124.outlook.office365.com (2603:10a6:209:85::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:29 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64088+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT056.mail.protection.outlook.com (10.152.19.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:29 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:29 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 1e320eb185b62973 X-CR-MTA-TID: 64aa7808 X-Received: from c2bd16e94ae6.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 51293C7F-BBE6-43AA-B028-F5D9A0D81FBF.1; Wed, 12 Aug 2020 15:23:23 +0000 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id c2bd16e94ae6.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:23 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Z2pXLW0N2AG0TmeWf1SZiw/rVUVmOndIyka5TTPXF7KFC23x8QxV+C6AVmw+l/m8gVVloMlFI31G31ypEhhlIMhL0FWOsLuK371dUfweNd0b3jQWtgz/o7Y8YLmrfgIwicfmShP8UR/obtM2t4YkpTHSm4p5Byqc0xGZFYfxOQL0KEziY96ND8iq9caF0J5inPfrPoYf6eVFLIOxOVu4EV4n677qfh+RrpSprZysIBCA1Ux07Uqvlz2cN2DgMKDqLYDEX8ZCh7Uha22kvuhJiglgJZwcZOCkTGyl9FZf5il2hC9mqCyk0LfjNq9iF0gP+Hu1sfOKjV7qqX6ZEpZ99w== 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-SenderADCheck; bh=qoUG7sYiElmZNNRdn6JkUv6nczDQjjKTeFTY48wUmIg=; b=Xb69+XRfHGzbdn8s4yU+IC1JvIJpT3uNnZR/eUcQ7IqZXhpp8QGhX1MGvKhICG9rKav7nJ5twzYrOt8HCc1kMH6HtbK2eMmWVfpDMRC/hdTCO12gkzFM0j0F4JvBYAC86u4znwoq8B93FycUV2by6zlsY/xeBEU37al02l15DUEz0/CK14sQbaMgElZWuViEPpKJY7kM++19CVNmjpzpi3ju8nZ8Cb3Qr4FqzYRdPoMVZfL2bfKtz1ZvuQK9JX1suk+4qD2W7u0VwI+mFl9UtXu7OgmkLq0bx0uNs54ghEDzPLcbcC8G8ODTY91XpjFu0PChfpiGU79RGSK9FQJz/A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6P193CA0008.EURP193.PROD.OUTLOOK.COM (2603:10a6:6:29::18) by AM0PR08MB3873.eurprd08.prod.outlook.com (2603:10a6:208:10c::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18; Wed, 12 Aug 2020 15:23:20 +0000 X-Received: from DB5EUR03FT018.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:29:cafe::6a) by DB6P193CA0008.outlook.office365.com (2603:10a6:6:29::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:20 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT018.mail.protection.outlook.com (10.152.20.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:20 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:16 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:16 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 10/30] DynamicTablesPkg: AML utility interfaces Date: Wed, 12 Aug 2020 16:22:16 +0100 Message-ID: <20200812152236.31164-11-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 627a6e05-e754-4af7-c201-08d83ed3aaa0 X-MS-TrafficTypeDiagnostic: AM0PR08MB3873:|VI1PR08MB3357: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:9508;OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: H8eXnrmgDweZzdrY/51n1XNZw/esKt5sz6blw6pXuu/Owm9f4S/WlvBpwb+jaLHXlF0X9djGICSfIpCSlovJX2zphptfdACBZG4Ae+p9RGiY4N9zlsJItGkgoTqoeVjiNT1MDT3XHxABhX8lSpSWECFD2goxNZgIVT9Skc/kqLZKllx5QwggYXPI6j04xQkYfaOPVovcxSd1MNXyFMS/s4DvbHz7lzCek/UY2U+Iv1nv2nGIq3Fk8RYJrEPZEREL/Q5u+Tw1QbgkKGDp27tcvnpZpljwbqv9kubmxHx01SspKncg+vxxvgRH9kCtQdJKa1WXOpAWtouY8wjOU131ab/W4Iz3Xs6wNbkUazjddWI8wXz9ILF3t2EsgQm9sW2NEXX1ARajZVjm+vjDw77cGQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(396003)(376002)(136003)(346002)(39860400002)(46966005)(7696005)(2906002)(19627235002)(478600001)(2616005)(70586007)(70206006)(83380400001)(1076003)(356005)(44832011)(82310400002)(30864003)(336012)(82740400003)(426003)(5660300002)(36756003)(186003)(4326008)(316002)(8936002)(6916009)(86362001)(8676002)(54906003)(47076004)(81166007)(26005);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB3873 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT056.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: b92b5439-2600-49a6-2cbd-08d83ed3a578 X-Microsoft-Antispam-Message-Info: 8pT9R0ccYYIB2Dq0Ks/khJX2xT8E9aMgBi33jxbh/oMYxcLL+y0lQqX1t3oWwCLcnT+CHIZEJgJcLm26hWKpS/hLYI+QxMop/P/OSDrgtkLO3uvJ9k2ig8gOJZP55VTqDl7YcrB3dIeYVmA8Nto6DJoHiV/oOkLfaYD53tkAEdZuORWIJ75kuUvM9lEDLqZbL8ln8Raa1KQUFCGVCY08gliGXnq3/8pK8W9XXVQB20wQ3xokroXi5sL2h3R9RviU0HwP1QPilqXbd9SNZ+QcsawkJky9EVScHIknPij2f+x13I/P/XgaXgb3/lDWYCWrrzgUma1p0+KjePN2DmZuB9VE2rQYAzKw/GH6fisNv/IVOc8ZYNDIltGn0oxWLhMTtKcBaTPnwLq4A90dICGmEA== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:29.3500 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 627a6e05-e754-4af7-c201-08d83ed3aaa0 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: VE1EUR03FT056.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB3357 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: uRO4JHXA0KD8ydkMgJux5s7Gx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245817; bh=2U8BAWcArLVDZnOh1q/hUQAKohLWJzVyBG8Vc/q2qBs=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=etd+GdtuTAGu1OEGuHD8SgOmEOcG93S/ca1KHd20JiM/btK7gm1idueXM269W5UydvW tz+nD1fIZxnh1vdziLfS1jvsOwq+XTWYF23Nn8EJrUNb/C9+vn5LS3EFvgeMmnbByTjfO nvCm0NHyjBm5ANRYmgGbPe/MmECqTUOLGHI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML utility interfaces are a collection of helper functions that assist in computing the checksum, size and to propagate the node information as a result of addition or update of AML nodes. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c | 906 ++++++++++= ++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h | 95 ++ 2 files changed, 1001 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c b/Dy= namicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c new file mode 100644 index 0000000000000000000000000000000000000000..7ebd08f945c0c5ae87a3408152a= efa6cc1e78234 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c @@ -0,0 +1,906 @@ +/** @file + AML Utility. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include + +/** This function computes and updates the ACPI table checksum. + + @param [in] AcpiTable Pointer to an Acpi table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AcpiPlatformChecksum ( + IN EFI_ACPI_DESCRIPTION_HEADER * AcpiTable + ) +{ + UINT8 * Ptr; + UINT8 Sum; + UINT32 Size; + + if (AcpiTable =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Ptr =3D (UINT8*)AcpiTable; + Size =3D AcpiTable->Length; + Sum =3D 0; + + // Set the checksum field to 0 first. + AcpiTable->Checksum =3D 0; + + // Compute the checksum. + while ((Size--) !=3D 0) { + Sum =3D (UINT8)(Sum + (*Ptr++)); + } + + // Set the checksum. + AcpiTable->Checksum =3D (UINT8)(0xFF - Sum + 1); + + return EFI_SUCCESS; +} + +/** A callback function that computes the size of a Node and adds it to the + Size pointer stored in the Context. + Calling this function on the root node will compute the total size of = the + AML bytestream. + + @param [in] Node Node to compute the size. + @param [in, out] Context Pointer holding the computed size. + (UINT32 *) Context. + @param [in, out] Status Pointer holding: + - At entry, the Status returned by the + last call to this exact function during + the enumeration; + - At exit, he returned status of the + call to this function. + Optional, can be NULL. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +STATIC +BOOLEAN +EFIAPI +AmlComputeSizeCallback ( + IN AML_NODE_HEADER * Node, + IN OUT VOID * Context, + IN OUT EFI_STATUS * Status OPTIONAL + ) +{ + UINT32 Size; + EAML_PARSE_INDEX IndexPtr; + CONST AML_OBJECT_NODE * ParentNode; + + if (!IS_AML_NODE_VALID (Node) || + (Context =3D=3D NULL)) { + ASSERT (0); + if (Status !=3D NULL) { + *Status =3D EFI_INVALID_PARAMETER; + } + return FALSE; + } + + // Ignore the second fixed argument of method invocation nodes + // as the information stored there (the argument count) is not in the + // ACPI specification. + ParentNode =3D (CONST AML_OBJECT_NODE*)AmlGetParent (Node); + if (IS_AML_OBJECT_NODE (ParentNode) && + AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0) && + AmlIsNodeFixedArgument (Node, &IndexPtr)) { + if (IndexPtr =3D=3D EAmlParseIndexTerm1) { + if (Status !=3D NULL) { + *Status =3D EFI_SUCCESS; + } + return TRUE; + } + } + + Size =3D *((UINT32*)Context); + + if (IS_AML_DATA_NODE (Node)) { + Size +=3D ((AML_DATA_NODE*)Node)->Size; + } else if (IS_AML_OBJECT_NODE (Node) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IS_PSEUDO_OPCODE)) { + // Ignore pseudo-opcodes as they are not part of the + // ACPI specification. + + Size +=3D (((AML_OBJECT_NODE*)Node)->AmlByteEncoding->OpCode =3D=3D + AML_EXT_OP) ? 2 : 1; + + // Add the size of the PkgLen. + if (AmlNodeHasAttribute ( + (AML_OBJECT_NODE*)Node, + AML_HAS_PKG_LENGTH)) { + Size +=3D AmlComputePkgLengthWidth (((AML_OBJECT_NODE*)Node)->PkgLen= ); + } + } + + // Check for overflow. + // The root node has a null size, thus the strict comparison. + if (*((UINT32*)Context) > Size) { + ASSERT (0); + *Status =3D EFI_INVALID_PARAMETER; + return FALSE; + } + + *((UINT32*)Context) =3D Size; + + if (Status !=3D NULL) { + *Status =3D EFI_SUCCESS; + } + + return TRUE; +} + +/** Compute the size of a tree/sub-tree. + + @param [in] Node Node to compute the size. + @param [in, out] Size Pointer holding the computed size. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlComputeSize ( + IN CONST AML_NODE_HEADER * Node, + IN OUT UINT32 * Size + ) +{ + EFI_STATUS Status; + + if (!IS_AML_NODE_VALID (Node) || + (Size =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *Size =3D 0; + + AmlEnumTree ( + (AML_NODE_HEADER*)Node, + AmlComputeSizeCallback, + (VOID*)Size, + &Status + ); + + return Status; +} + +/** Get the value contained in an integer node. + + @param [in] Node Pointer to an integer node. + Must be an object node. + @param [out] Value Value contained in the integer node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlNodeGetIntegerValue ( + IN AML_OBJECT_NODE * Node, + OUT UINT64 * Value + ) +{ + AML_DATA_NODE * DataNode; + + if ((!IsIntegerNode (Node) && + !IsSpecialIntegerNode (Node)) || + (Value =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // For ZeroOp and OneOp, there is no data node. + if (IsSpecialIntegerNode (Node)) { + if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) { + *Value =3D 0; + } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) { + *Value =3D 1; + } else { + // OnesOp cannot be handled: it represents a maximum value. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; + } + + // For integer nodes, the value is in the first fixed argument. + DataNode =3D (AML_DATA_NODE*)Node->FixedArgs[EAmlParseIndexTerm0]; + if (!IS_AML_DATA_NODE (DataNode) || + (DataNode->DataType !=3D EAmlNodeDataTypeUInt)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + switch (DataNode->Size) { + case 1: + { + *Value =3D *((UINT8*)(DataNode->Buffer)); + break; + } + case 2: + { + *Value =3D *((UINT16*)(DataNode->Buffer)); + break; + } + case 4: + { + *Value =3D *((UINT32*)(DataNode->Buffer)); + break; + } + case 8: + { + *Value =3D *((UINT64*)(DataNode->Buffer)); + break; + } + default: + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } // switch + + return EFI_SUCCESS; +} + +/** Replace a Zero (AML_ZERO_OP) or One (AML_ONE_OP) object node + with a byte integer (AML_BYTE_PREFIX) object node having the same valu= e. + + @param [in] Node Pointer to an integer node. + Must be an object node having ZeroOp or OneOp. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlUnwindSpecialInteger ( + IN AML_OBJECT_NODE * Node + ) +{ + EFI_STATUS Status; + + AML_DATA_NODE * NewDataNode; + UINT8 Value; + CONST AML_BYTE_ENCODING * ByteEncoding; + + if (!IsSpecialIntegerNode (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Find the value. + if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) { + Value =3D 0; + } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) { + Value =3D 1; + } else { + // OnesOp cannot be handled: it represents a maximum value. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeUInt, + &Value, + sizeof (UINT8), + (AML_DATA_NODE**)&NewDataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Change the encoding of the special node to a ByteOp encoding. + ByteEncoding =3D AmlGetByteEncodingByOpCode (AML_BYTE_PREFIX, 0); + if (ByteEncoding =3D=3D NULL) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + + // Update the ByteEncoding from ZERO_OP/ONE_OP to AML_BYTE_PREFIX. + Node->AmlByteEncoding =3D ByteEncoding; + + // Add the data node as the first fixed argument of the ByteOp object. + Status =3D AmlSetFixedArgument ( + (AML_OBJECT_NODE*)Node, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)NewDataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + AmlDeleteTree ((AML_NODE_HEADER*)NewDataNode); + return Status; +} + +/** Set the value contained in an integer node. + + The OpCode is updated accordingly to the new value + (e.g.: If the original value was a UINT8 value, then the OpCode + would be AML_BYTE_PREFIX. If it the new value is a UINT16 + value then the OpCode will be updated to AML_WORD_PREFIX). + + @param [in] Node Pointer to an integer node. + Must be an object node. + @param [in] NewValue New value to write in the integer node. + @param [out] ValueWidthDiff Difference in number of bytes used to store + the new value. + Can be negative. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlNodeSetIntegerValue ( + IN AML_OBJECT_NODE * Node, + IN UINT64 NewValue, + OUT INT8 * ValueWidthDiff + ) +{ + EFI_STATUS Status; + AML_DATA_NODE * DataNode; + + UINT8 NewOpCode; + UINT8 NumberOfBytes; + + if ((!IsIntegerNode (Node) && + !IsSpecialIntegerNode (Node)) || + (ValueWidthDiff =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *ValueWidthDiff =3D 0; + // For ZeroOp and OneOp, there is no data node. + // Thus the object node is converted to a byte object node holding 0 or = 1. + if (IsSpecialIntegerNode (Node)) { + switch (NewValue) { + case AML_ZERO_OP: + Node->AmlByteEncoding =3D AmlGetByteEncodingByOpCode (AML_ZERO_OP,= 0); + return EFI_SUCCESS; + case AML_ONE_OP: + Node->AmlByteEncoding =3D AmlGetByteEncodingByOpCode (AML_ONE_OP, = 0); + return EFI_SUCCESS; + default: + { + Status =3D AmlUnwindSpecialInteger (Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + // The AmlUnwindSpecialInteger functions converts a special integer + // node to a UInt8/Byte data node. Thus, the size increments by on= e: + // special integer are encoded as one byte (the opcode only) while= byte + // integers are encoded as two bytes (the opcode + the value). + *ValueWidthDiff +=3D sizeof (UINT8); + } + } // switch + } // IsSpecialIntegerNode (Node) + + // For integer nodes, the value is in the first fixed argument. + DataNode =3D (AML_DATA_NODE*)Node->FixedArgs[EAmlParseIndexTerm0]; + if (!IS_AML_DATA_NODE (DataNode) || + (DataNode->DataType !=3D EAmlNodeDataTypeUInt)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The value can be encoded with a special 0 or 1 OpCode. + // The AML_ONES_OP is not handled. + if (NewValue <=3D 1) { + NewOpCode =3D (NewValue =3D=3D 0) ? AML_ZERO_OP : AML_ONE_OP; + Node->AmlByteEncoding =3D AmlGetByteEncodingByOpCode (NewOpCode, 0); + + // The value is encoded with a AML_ZERO_OP or AML_ONE_OP. + // This means there is no need for a DataNode containing the value. + // The change in size is equal to the size of the DataNode's buffer. + *ValueWidthDiff =3D -((INT8)DataNode->Size); + + // Detach and free the DataNode containing the integer value. + DataNode->NodeHeader.Parent =3D NULL; + Node->FixedArgs[EAmlParseIndexTerm0] =3D NULL; + Status =3D AmlDeleteNode ((AML_NODE_HEADER*)DataNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + return EFI_SUCCESS; + } + + // Check the number of bits needed to represent the value. + if (NewValue > MAX_UINT32) { + // Value is 64 bits. + NewOpCode =3D AML_QWORD_PREFIX; + NumberOfBytes =3D 8; + } else if (NewValue > MAX_UINT16) { + // Value is 32 bits. + NewOpCode =3D AML_DWORD_PREFIX; + NumberOfBytes =3D 4; + } else if (NewValue > MAX_UINT8) { + // Value is 16 bits. + NewOpCode =3D AML_WORD_PREFIX; + NumberOfBytes =3D 2; + } else { + // Value is 8 bits. + NewOpCode =3D AML_BYTE_PREFIX; + NumberOfBytes =3D 1; + } + + *ValueWidthDiff +=3D (INT8)(NumberOfBytes - DataNode->Size); + + // Update the ByteEncoding as it may have changed between [8 .. 64] bits. + Node->AmlByteEncoding =3D AmlGetByteEncodingByOpCode (NewOpCode, 0); + if (Node->AmlByteEncoding =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Free the old DataNode buffer and allocate a buffer with the right size + // to store the new data. + if (*ValueWidthDiff !=3D 0) { + FreePool (DataNode->Buffer); + DataNode->Buffer =3D AllocateZeroPool (NumberOfBytes); + if (DataNode->Buffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + DataNode->Size =3D NumberOfBytes; + } + + // Write the new value. + CopyMem (DataNode->Buffer, &NewValue, NumberOfBytes); + + return EFI_SUCCESS; +} + +/** Increment/decrement the value contained in the IntegerNode. + + @param [in] IntegerNode Pointer to an object node containing + an integer. + @param [in] IsIncrement Choose the operation to do: + - TRUE: Increment the Node's size and + the Node's count; + - FALSE: Decrement the Node's size and + the Node's count. + @param [in] Diff Value to add/subtract to the integer. + @param [out] ValueWidthDiff When modifying the integer, it can be + promoted/demoted, e.g. from UINT8 to UINT1= 6. + Stores the change in width. + Can be negative. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlNodeUpdateIntegerValue ( + IN AML_OBJECT_NODE * IntegerNode, + IN BOOLEAN IsIncrement, + IN UINT64 Diff, + OUT INT8 * ValueWidthDiff + ) +{ + EFI_STATUS Status; + UINT64 Value; + + if (ValueWidthDiff =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the current value. + // Checks on the IntegerNode are done in the call. + Status =3D AmlNodeGetIntegerValue (IntegerNode, &Value); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Check for UINT64 over/underflow. + if ((IsIncrement && (Value > (MAX_UINT64 - Diff))) || + (!IsIncrement && (Value < Diff))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Compute the new value. + if (IsIncrement) { + Value +=3D Diff; + } else { + Value -=3D Diff; + } + + Status =3D AmlNodeSetIntegerValue ( + IntegerNode, + Value, + ValueWidthDiff + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Propagate the size information up the tree. + + The length of the ACPI table is updated in the RootNode, + but not the checksum. + + @param [in] Node Pointer to a node. + Must be a root node or an object node. + @param [in] IsIncrement Choose the operation to do: + - TRUE: Increment the Node's size and + the Node's count; + - FALSE: Decrement the Node's size and + the Node's count. + @param [in] Diff Value to add/subtract to the Node's size. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlPropagateSize ( + IN AML_NODE_HEADER * Node, + IN BOOLEAN IsIncrement, + IN UINT32 * Diff + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + AML_NODE_HEADER * ParentNode; + + UINT32 Value; + UINT32 InitialPkgLenWidth; + UINT32 NewPkgLenWidth; + UINT32 ReComputedPkgLenWidth; + INT8 FieldWidthChange; + + if (!IS_AML_OBJECT_NODE (Node) && + !IS_AML_ROOT_NODE (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (IS_AML_OBJECT_NODE (Node)) { + ObjectNode =3D (AML_OBJECT_NODE*)Node; + + // For BufferOp, the buffer size is stored in BufferSize. Therefore, + // BufferOp needs special handling to update the BufferSize. + // BufferSize must be updated before the PkgLen to accommodate any + // increment resulting from the update of the BufferSize. + // DefBuffer :=3D BufferOp PkgLength BufferSize ByteList + // BufferOp :=3D 0x11 + // BufferSize :=3D TermArg =3D> Integer + if (AmlNodeCompareOpCode (ObjectNode, AML_BUFFER_OP, 0)) { + // First fixed argument of BufferOp is an integer (BufferSize) + // (can be a BYTE, WORD, DWORD or QWORD). + // BufferSize is an object node. + Status =3D AmlNodeUpdateIntegerValue ( + (AML_OBJECT_NODE*)AmlGetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0 + ), + IsIncrement, + (UINT64)(*Diff), + &FieldWidthChange + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // FieldWidthChange is an integer. + // It must be positive if IsIncrement is TRUE, negative otherwise. + if ((IsIncrement && + (FieldWidthChange < 0)) || + (!IsIncrement && + (FieldWidthChange > 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check for UINT32 overflow. + if (*Diff > (MAX_UINT32 - (UINT32)ABS (FieldWidthChange))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update Diff if the field width changed. + *Diff =3D (UINT32)(*Diff + ABS (FieldWidthChange)); + } // AML_BUFFER_OP node. + + // Update the PgkLen. + // Needs to be done at last to reflect the potential field width chang= es. + if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) { + Value =3D ObjectNode->PkgLen; + + // Subtract the size of the PkgLen encoding. The size of the PkgLen + // encoding must be computed after having updated Value. + InitialPkgLenWidth =3D AmlComputePkgLengthWidth (Value); + Value -=3D InitialPkgLenWidth; + + // Check for an over/underflows. + // PkgLen is a 28 bit value, cf 20.2.4 Package Length Encoding + // i.e. the maximum value is (2^28 - 1) =3D ((BIT0 << 28) - 1). + if ((IsIncrement && ((((BIT0 << 28) - 1) - Value) < *Diff)) || + (!IsIncrement && (Value < *Diff))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update the size. + if (IsIncrement) { + Value +=3D *Diff; + } else { + Value -=3D *Diff; + } + + // Compute the new PkgLenWidth. + NewPkgLenWidth =3D AmlComputePkgLengthWidth (Value); + if (NewPkgLenWidth =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Add it to the Value. + Value +=3D NewPkgLenWidth; + + // Check that adding the PkgLenWidth didn't trigger a domino effect, + // increasing the encoding width of the PkgLen again. + // The PkgLen is encoded on at most 4 bytes. It is possible to incre= ase + // the PkgLen width if its encoding is on less than 3 bytes. + ReComputedPkgLenWidth =3D AmlComputePkgLengthWidth (Value); + if (ReComputedPkgLenWidth !=3D NewPkgLenWidth) { + if ((ReComputedPkgLenWidth !=3D 0) && + (ReComputedPkgLenWidth < 4)) { + // No need to recompute the PkgLen since a new threshold cannot + // be reached by incrementing the value by one. + Value +=3D 1; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + *Diff +=3D (InitialPkgLenWidth > ReComputedPkgLenWidth) ? + (InitialPkgLenWidth - ReComputedPkgLenWidth) : + (ReComputedPkgLenWidth - InitialPkgLenWidth); + ObjectNode->PkgLen =3D Value; + } // PkgLen update. + + // During CodeGeneration, the tree is incomplete and + // there is no root node at the top of the tree. Stop + // propagating the new size when finding a root node + // OR when a NULL parent is found. + ParentNode =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (ParentNode !=3D NULL) { + // Propagate the size up the tree. + Status =3D AmlPropagateSize ( + Node->Parent, + IsIncrement, + Diff + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + } else if (IS_AML_ROOT_NODE (Node)) { + // Update the length field in the SDT header. + Value =3D ((AML_ROOT_NODE*)Node)->SdtHeader->Length; + + // Check for an over/underflows. + if ((IsIncrement && (Value > (MAX_UINT32 - *Diff))) || + (!IsIncrement && (Value < *Diff))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update the size. + if (IsIncrement) { + Value +=3D *Diff; + } else { + Value -=3D *Diff; + } + + ((AML_ROOT_NODE*)Node)->SdtHeader->Length =3D Value; + } + + return EFI_SUCCESS; +} + +/** Propagate the node count information up the tree. + + @param [in] ObjectNode Pointer to an object node. + @param [in] IsIncrement Choose the operation to do: + - TRUE: Increment the Node's size and + the Node's count; + - FALSE: Decrement the Node's size and + the Node's count. + @param [in] NodeCount Number of nodes added/removed (depends o= n the + value of Operation). + @param [out] FieldWidthChange When modifying the integer, it can be + promoted/demoted, e.g. from UINT8 to UIN= T16. + Stores the change in width. + Can be negative. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlPropagateNodeCount ( + IN AML_OBJECT_NODE * ObjectNode, + IN BOOLEAN IsIncrement, + IN UINT8 NodeCount, + OUT INT8 * FieldWidthChange + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * NodeCountArg; + UINT8 CurrNodeCount; + + // Currently there is no use case where (NodeCount > 1). + if (!IS_AML_OBJECT_NODE (ObjectNode) || + (FieldWidthChange =3D=3D NULL) || + (NodeCount > 1)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *FieldWidthChange =3D 0; + + // Update the number of elements stored in PackageOp and VarPackageOp. + // The number of elements is stored as the first fixed argument. + // DefPackage :=3D PackageOp PkgLength NumElements PackageElementList + // PackageOp :=3D 0x12 + // DefVarPackage :=3D VarPackageOp PkgLength VarNumElements PackageEleme= ntList + // VarPackageOp :=3D 0x13 + // NumElements :=3D ByteData + // VarNumElements :=3D TermArg =3D> Integer + NodeCountArg =3D AmlGetFixedArgument (ObjectNode, EAmlParseIndexTerm0); + if (AmlNodeCompareOpCode (ObjectNode, AML_PACKAGE_OP, 0)) { + // First fixed argument of PackageOp stores the number of elements + // in the package. It is an UINT8. + + // Check for over/underflow. + CurrNodeCount =3D *(((AML_DATA_NODE*)NodeCountArg)->Buffer); + if ((IsIncrement && (CurrNodeCount =3D=3D MAX_UINT8)) || + (!IsIncrement && (CurrNodeCount =3D=3D 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update the node count in the DataNode. + CurrNodeCount =3D IsIncrement ? (CurrNodeCount + 1) : (CurrNodeCount -= 1); + *(((AML_DATA_NODE*)NodeCountArg)->Buffer) =3D CurrNodeCount; + } else if (AmlNodeCompareOpCode (ObjectNode, AML_VAR_PACKAGE_OP, 0)) { + // First fixed argument of PackageOp stores the number of elements + // in the package. It is an integer (can be a BYTE, WORD, DWORD, QWORD= ). + Status =3D AmlNodeUpdateIntegerValue ( + (AML_OBJECT_NODE*)NodeCountArg, + IsIncrement, + NodeCount, + FieldWidthChange + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** Propagate information up the tree. + + The information can be a new size, a new number of arguments. + + @param [in] Node Pointer to a node. + Must be a root node or an object node. + @param [in] IsIncrement Choose the operation to do: + - TRUE: Increment the Node's size and + the Node's count; + - FALSE: Decrement the Node's size and + the Node's count. + @param [in] Diff Value to add/subtract to the Node's size. + @param [in] NodeCount Number of nodes added/removed. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlPropagateInformation ( + IN AML_NODE_HEADER * Node, + IN BOOLEAN IsIncrement, + IN UINT32 Diff, + IN UINT8 NodeCount + ) +{ + EFI_STATUS Status; + INT8 FieldWidthChange; + + // Currently there is no use case where (NodeCount > 1). + if ((!IS_AML_ROOT_NODE (Node) && + !IS_AML_OBJECT_NODE (Node)) || + (NodeCount > 1)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Propagate the node count first as it may change the number of bytes + // needed to store the node count, and then impact FieldWidthChange. + if ((NodeCount !=3D 0) && + IS_AML_OBJECT_NODE (Node)) { + Status =3D AmlPropagateNodeCount ( + (AML_OBJECT_NODE*)Node, + IsIncrement, + NodeCount, + &FieldWidthChange + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Propagate the potential field width change. + // Maximum change is between UINT8/UINT64: 8 bytes. + if ((ABS (FieldWidthChange) > 8) || + (IsIncrement && + ((FieldWidthChange < 0) || + ((Diff + (UINT8)FieldWidthChange) > MAX_UINT32))) || + (!IsIncrement && + ((FieldWidthChange > 0) || + (Diff < (UINT32)ABS (FieldWidthChange))))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + Diff =3D (UINT32)(Diff + (UINT8)ABS (FieldWidthChange)); + } + + // Diff can be zero if some data is updated without modifying the data s= ize. + if (Diff !=3D 0) { + Status =3D AmlPropagateSize (Node, IsIncrement, &Diff); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h b/Dy= namicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h new file mode 100644 index 0000000000000000000000000000000000000000..c57d780140d4f053a225032fb6f= c4e7b9991896d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h @@ -0,0 +1,95 @@ +/** @file + AML Utility. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_UTILITY_H_ +#define AML_UTILITY_H_ + +#include + +/** This function computes and updates the ACPI table checksum. + + @param [in] AcpiTable Pointer to an Acpi table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AcpiPlatformChecksum ( + IN EFI_ACPI_DESCRIPTION_HEADER * AcpiTable + ); + +/** Compute the size of a tree/sub-tree. + + @param [in] Node Node to compute the size. + @param [in, out] Size Pointer holding the computed size. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlComputeSize ( + IN CONST AML_NODE_HEADER * Node, + IN OUT UINT32 * Size + ); + +/** Set the value contained in an integer node. + + The OpCode is updated accordingly to the new value + (e.g.: If the original value was a UINT8 value, then the OpCode + would be AML_BYTE_PREFIX. If it the new value is a UINT16 + value then the OpCode will be updated to AML_WORD_PREFIX). + + @param [in] Node Pointer to an integer node. + Must be an object node. + @param [in] NewValue New value to write in the integer node. + @param [out] ValueWidthDiff Difference in number of bytes used to store + the new value. + Can be negative. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlNodeSetIntegerValue ( + IN AML_OBJECT_NODE * Node, + IN UINT64 NewValue, + OUT INT8 * ValueWidthDiff + ); + +/** Propagate information up the tree. + + The information can be a new size, a new number of arguments. + + @param [in] Node Pointer to a node. + Must be a root node or an object node. + @param [in] IsIncrement Choose the operation to do: + - TRUE: Increment the Node's size and + the Node's count; + - FALSE: Decrement the Node's size and + the Node's count. + @param [in] Diff Value to add/subtract to the Node's size. + @param [in] NodeCount Number of nodes added/removed. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlPropagateInformation ( + IN AML_NODE_HEADER * Node, + IN BOOLEAN IsIncrement, + IN UINT32 Diff, + IN UINT8 NodeCount + ); + +#endif // AML_UTILITY_H_ + --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64088): https://edk2.groups.io/g/devel/message/64088 Mute This Topic: https://groups.io/mt/76149156/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64091+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245825253944.0684753198794; Wed, 12 Aug 2020 08:23:45 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id dsfOYY1788612x5joUQXftMX; Wed, 12 Aug 2020 08:23:44 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.55]) by mx.groups.io with SMTP id smtpd.web12.16974.1597245814871165458 for ; Wed, 12 Aug 2020 08:23:35 -0700 X-Received: from AM5PR0402CA0002.eurprd04.prod.outlook.com (2603:10a6:203:90::12) by DBBPR08MB4726.eurprd08.prod.outlook.com (2603:10a6:10:f0::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:30 +0000 X-Received: from AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:90:cafe::4) by AM5PR0402CA0002.outlook.office365.com (2603:10a6:203:90::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:30 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64091+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT059.mail.protection.outlook.com (10.152.17.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:30 +0000 X-Received: ("Tessian outbound e8cdb8c6f386:v64"); Wed, 12 Aug 2020 15:23:30 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 04acb9250c3a939f X-CR-MTA-TID: 64aa7808 X-Received: from a6d21fb28bac.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id EE45680E-A859-4FA5-88F3-337866ABD8EE.1; Wed, 12 Aug 2020 15:23:25 +0000 X-Received: from EUR02-AM5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id a6d21fb28bac.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:25 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=awKC5t0bXVQIPjm/zI4nFgZFpR/ZhRWIAcnJe1weKs0mRWnQcgE5BubzrjK4ulWGp4TBv6XPE58gg2baNorWpef8Sw6VSvT1kyf8+cJYIV4eeKrMsFQuNBaZPudBjSlNYVUZL2IDRWDzmoWeYC//c+N/ASyZlrX57HrJtlgiuJ7KzqVTWNWC58oIMXT+gtpkEkok9cgvxGNLVEs1Yi6Nos0gKDMdgZbpuRYrgEHJEag/PN7uIbdRRYBnowBnedcmM7ETiN8tPUbXJC7wzRcbbCtaKXHNKSiKICiW7uKaVx2FY+Qub3/U2nm1EURIen+7KgAP7hEj7ZAPB003nIFtfQ== 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-SenderADCheck; bh=/ES7mQNOnXecVqvlmqz5j+cxs8S6sW9X5adCB4BBW84=; b=CkPM0CNClSi5uNDXoUdIfFkUYOE6pEnqPLHIAL7rEZQMQ6/T/R0avD3fOGqeaaA98VocN6/8xmfVx8xLjz0JP0WScyYCOQsBnzmyG5qwNzq0023ugBUg0o4ryp7HXaPA/YzN+FqAf6p1UDLCO9S4VNs2cztcp5hzkDcehuS+MSnabPrfuHD09EPO8GHGb22ZaLRe5dIrSAgDm7FZO1FrbHtzlXK7vA4MUnzxM44KVqfQ2VmKh7vd5uVWUkRNKikVq7uAETboGLqEmOBbl4LGUjwKLMjsG4w0bRFFaqC72ydf4GQ+lRX3FejuO6OlVC9iRUsxYqb7ao2ORLYJ6tadww== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6P193CA0013.EURP193.PROD.OUTLOOK.COM (2603:10a6:6:29::23) by DBBPR08MB4839.eurprd08.prod.outlook.com (2603:10a6:10:da::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18; Wed, 12 Aug 2020 15:23:22 +0000 X-Received: from DB5EUR03FT018.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:29:cafe::b) by DB6P193CA0013.outlook.office365.com (2603:10a6:6:29::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:22 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT018.mail.protection.outlook.com (10.152.20.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:22 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:19 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:18 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 11/30] DynamicTablesPkg: AML and ASL string helper Date: Wed, 12 Aug 2020 16:22:17 +0100 Message-ID: <20200812152236.31164-12-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 90bf6050-6cb7-4b14-5c6d-08d83ed3ab72 X-MS-TrafficTypeDiagnostic: DBBPR08MB4839:|DBBPR08MB4726: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:172;OLM:172; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: EhlMlGsQDIWRHdqKYuxgthLuASVlhegcTvrPOQitloBwqXgEteTX+LEVDCNnN178E+b7N+IDq3XJJTblMN6HofJVqX3LaeLWRD66vB+gbsMFGNdaLri2wWg37PwHBjW8yL4OlN+MbH9rHxDkF7YXM+eKC7GyPN7s5VwgQMScJTE+h/r62JOGn1qH3aksDspCW14wpxdxe0BLQFg1VJzWPLz6Y0/uWX+MyxmMplf/UzaiE+tDOZs/0nAlmTc82eWvlU4dYS5Detaike5IDpv9RN9YIikBpSs0iNWqxlFCrliuq64HgRfElZvK6a/YrCWLFwCFqRheu9y+qGrHZI5a3h7eq1mJYB8kU8jJE81EhabiJNBRLiB/t353359jaFYepBIeRJeVccoS39GmGltaBw== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(396003)(39860400002)(376002)(136003)(346002)(46966005)(36756003)(426003)(2616005)(5660300002)(336012)(356005)(44832011)(7696005)(26005)(86362001)(83380400001)(82740400003)(82310400002)(81166007)(47076004)(186003)(1076003)(316002)(2906002)(54906003)(30864003)(478600001)(70206006)(6916009)(8676002)(4326008)(8936002)(70586007)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4839 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 63547d22-cb74-438c-732f-08d83ed3a67b X-Microsoft-Antispam-Message-Info: i8rtzXV21JN+R+yBcS1bHiFinXfDJeOMgkCECyMkJFqb+HskFidY7f+DqmomoDU0tPdevmGVEynekXRB3SxV8ed4d356h3TwvvT8ktBOTXe7x3RXooQFzsD/PJZaqglhtZmr3I+4X9xS3k66WeeMUcw/LnLwvD2mu2Xe/nIDi1qHpr6svVi/ffmjKDGlJUdCEWCNAGUrMI/MWM2m+mbSX9tYYmawR/d4dhF6YLszGbsYe/as3HOSJ6SsH5V2efPVROyW9h7wVRNSwvzEEYmI6ouQgdkv48/kM2zCIKIcSyAmNErQAr40G+SpyGQ9e+mUkFNV/xWTeaZ+JiwSETwMOqqyubOrjwaSM18tXkQ4lNH5g4CQdvdGROaK4kNXVdAV++N0CQ9Ex6YItgcZYX+s5A== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:30.7635 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 90bf6050-6cb7-4b14-5c6d-08d83ed3ab72 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: AM5EUR03FT059.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4726 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: agGdJCgd86Xq09mfDo1F992jx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245824; bh=szxAjbXllQW6vxzVdX1kNe0zttckmtq5LApyfnrqX3E=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=Ni/4xHRFYZLoEH2T46QLQDQi7PwXxpeNNJqz5bdv1wiaiCbwemtxwbqipcBWJJ7/9D0 4g/tt8JIpzBWOyzByLrf1kICq3ybc4xCHEyb5JzEmkdJA+RqY3w1+kCIQN87QOH8Zc1E7 Bv0iy9CYhzwh1JnMoxKk/Q8RzsJ26NJR/SU= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Dynamic AML requires encoding/decoding and conversion of AML and ASL strings. A collection of helper functions have been provided for internal use in the AmlLib Library. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c | 1022 +++++++++= +++++++++++ DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h | 401 ++++++++ 2 files changed, 1423 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c b/Dy= namicTablesPkg/Library/Common/AmlLib/String/AmlString.c new file mode 100644 index 0000000000000000000000000000000000000000..e9d36f4b6c710cc9a22968d234b= b4be720523bb4 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c @@ -0,0 +1,1022 @@ +/** @file + AML String. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include + +/** Check NameString/path information is valid. + + Root, ParentPrefix and SegCount cannot be 0 at the same time. + This function works for ASL and AML name strings. + + @param [in] Root Number of root char. + Must be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Must be [0-255]. + @param [in] SegCount Number of NameSeg (s). + Must be [0-255]. + + @retval TRUE id the input information is in the right boundaries. + FALSE otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsNameString ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ) +{ + if (((Root =3D=3D 0) || (Root =3D=3D 1)) && + (ParentPrefix <=3D MAX_UINT8) && + (!((ParentPrefix !=3D 0) && (Root !=3D 0))) && + (SegCount <=3D MAX_UINT8) && + ((SegCount + Root + ParentPrefix) !=3D 0)) { + return TRUE; + } + return FALSE; +} + +/** Copy bytes from SrcBuffer to DstBuffer and convert to upper case. + Don't copy more than MaxDstBufferSize bytes. + + @param [out] DstBuffer Destination buffer. + @param [in] MaxDstBufferSize Maximum size of DstBuffer. + Must be non-zero. + @param [in] SrcBuffer Source buffer. + @param [in] Count Count of bytes to copy from SrcBuffer. + Return success if 0. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpperCaseMemCpyS ( + OUT CHAR8 * DstBuffer, + IN UINT32 MaxDstBufferSize, + IN CONST CHAR8 * SrcBuffer, + IN UINT32 Count + ) +{ + UINT32 Index; + + if ((DstBuffer =3D=3D NULL) || + (SrcBuffer =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (Count =3D=3D 0) { + return EFI_SUCCESS; + } + + if (Count > MaxDstBufferSize) { + Count =3D MaxDstBufferSize; + } + + for (Index =3D 0; Index < Count; Index++) { + if ((SrcBuffer[Index] >=3D 'a') && (SrcBuffer[Index] <=3D 'z')) { + DstBuffer[Index] =3D (CHAR8)((UINT8)SrcBuffer[Index] - ('a' - 'A')); + } else { + DstBuffer[Index] =3D SrcBuffer[Index]; + } + } + + return EFI_SUCCESS; +} + +/** Check whether Buffer is a root path ('\'). + + This function works for both ASL and AML pathnames. + Buffer must be at least 2 bytes long. + + @param [in] Buffer An ASL/AML path. + + @retval TRUE Buffer is a root path + @retval FALSE Buffer is not a root path. +**/ +BOOLEAN +EFIAPI +AmlIsRootPath ( + IN CONST CHAR8 * Buffer + ) +{ + if (Buffer =3D=3D NULL) { + return FALSE; + } + + if ((Buffer[0] =3D=3D AML_ROOT_CHAR) && (Buffer[1] =3D=3D '\0')) { + return TRUE; + } else { + return FALSE; + } +} + +/** Check whether Ch is an ASL/AML LeadName. + + This function works for both ASL and AML pathnames. + + ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms": + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + + ACPI 6.3 specification, s20.2.2. "Name Objects Encoding": + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + + @param [in] Ch The char to test. + + @retval TRUE Ch is an ASL/AML LeadName. + @retval FALSE Ch is not an ASL/AML LeadName. +**/ +BOOLEAN +EFIAPI +AmlIsLeadNameChar ( + IN CHAR8 Ch + ) +{ + if ((Ch =3D=3D '_') || (Ch >=3D 'A' && Ch <=3D 'Z') || (Ch >=3D 'a' && C= h <=3D 'z')) { + return TRUE; + } else { + return FALSE; + } +} + +/** Check whether Ch is an ASL/AML NameChar. + + This function works for both ASL and AML pathnames. + + ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms": + NameChar :=3D DigitChar | LeadNameChar + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + DigitChar :=3D '0'-'9' + + ACPI 6.3 specification, s20.2.2. "Name Objects Encoding": + NameChar :=3D DigitChar | LeadNameChar + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + DigitChar :=3D '0'-'9' + + @param [in] Ch The char to test. + + @retval TRUE Ch is an ASL/AML NameChar. + @retval FALSE Ch is not an ASL/AML NameChar. +**/ +BOOLEAN +EFIAPI +AmlIsNameChar ( + IN CHAR8 Ch + ) +{ + if (AmlIsLeadNameChar (Ch) || (Ch >=3D '0' && Ch <=3D '9')) { + return TRUE; + } else { + return FALSE; + } +} + +/** Check whether AslBuffer is an ASL NameSeg. + + This function only works for ASL NameStrings/pathnames. + ASL NameStrings/pathnames are at most 4 chars long. + + @param [in] AslBuffer Pointer in an ASL NameString/pathname. + @param [out] Size Size of the NameSeg. + + @retval TRUE AslBuffer is an ASL NameSeg. + @retval FALSE AslBuffer is not an ASL NameSeg. +**/ +BOOLEAN +EFIAPI +AslIsNameSeg ( + IN CONST CHAR8 * AslBuffer, + OUT UINT32 * Size + ) +{ + UINT32 Index; + + if ((AslBuffer =3D=3D NULL) || + (Size =3D=3D NULL)) { + return FALSE; + } + + if (!AmlIsLeadNameChar (AslBuffer[0])) { + return FALSE; + } + + for (Index =3D 1; Index < AML_NAME_SEG_SIZE; Index++) { + if ((AslBuffer[Index] =3D=3D '.') || + (AslBuffer[Index] =3D=3D '\0')) { + *Size =3D Index; + return TRUE; + } else if (!AmlIsNameChar (AslBuffer[Index])) { + return FALSE; + } + } + + *Size =3D Index; + return TRUE; +} + +/** Check whether AmlBuffer is an AML NameSeg. + + This function only works for AML NameStrings/pathnames. + AML NameStrings/pathnames must be 4 chars long. + + @param [in] AmlBuffer Pointer in an AML NameString/pathname. + + @retval TRUE AmlBuffer is an AML NameSeg. + @retval FALSE AmlBuffer is not an AML NameSeg. +**/ +BOOLEAN +EFIAPI +AmlIsNameSeg ( + IN CONST CHAR8 * AmlBuffer + ) +{ + UINT32 Index; + + if (AmlBuffer =3D=3D NULL) { + return FALSE; + } + + if (!AmlIsLeadNameChar (AmlBuffer[0])) { + return FALSE; + } + + for (Index =3D 1; Index < AML_NAME_SEG_SIZE; Index++) { + if (!AmlIsNameChar (AmlBuffer[Index])) { + return FALSE; + } + } + + return TRUE; +} + +/** Parse an ASL NameString/path. + + An ASL NameString/path must be NULL terminated. + Information found in the ASL NameString/path is returned via pointers: + Root, ParentPrefix, SegCount. + + @param [in] Buffer ASL NameString/path. + @param [out] Root Pointer holding the number of root char. + Can be 0 or 1. + @param [out] ParentPrefix Pointer holding the number of carets char ('= ^'). + Can be [0-255]. + @param [out] SegCount Pointer holding the number of NameSeg (s). + Can be [0-255]. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AslParseNameStringInfo ( + IN CONST CHAR8 * Buffer, + OUT UINT32 * Root, + OUT UINT32 * ParentPrefix, + OUT UINT32 * SegCount + ) +{ + UINT32 NameSegSize; + + if ((Buffer =3D=3D NULL) || + (Root =3D=3D NULL) || + (ParentPrefix =3D=3D NULL) || + (SegCount =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *Root =3D 0; + *ParentPrefix =3D 0; + *SegCount =3D 0; + + // Handle Root and ParentPrefix(s). + if (*Buffer =3D=3D AML_ROOT_CHAR) { + *Root =3D 1; + Buffer++; + } else if (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR) { + do { + Buffer++; + (*ParentPrefix)++; + } while (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR); + } + + // Handle SegCount(s). + while (AslIsNameSeg (Buffer, &NameSegSize)) { + // Safety checks on NameSegSize. + if ((NameSegSize =3D=3D 0) || (NameSegSize > AML_NAME_SEG_SIZE)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Increment the NameSeg count. + (*SegCount)++; + Buffer +=3D NameSegSize; + + // Skip the '.' separator if present. + if (*Buffer =3D=3D '.') { + Buffer++; + } + } // while + + // An ASL NameString/path must be NULL terminated. + if (*Buffer !=3D '\0') { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** Parse an AML NameString/path. + + It is possible to determine the size of an AML NameString/path just + by sight reading it. So no overflow can occur. + Information found in the AML NameString/path is returned via pointers: + Root, ParentPrefix, SegCount. + + @param [in] Buffer AML NameString/path. + @param [out] Root Pointer holding the number of root char. + Can be 0 or 1. + @param [out] ParentPrefix Pointer holding the number of carets char = ('^'). + Can be [0-255]. + @param [out] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlParseNameStringInfo ( + IN CONST CHAR8 * Buffer, + OUT UINT32 * Root, + OUT UINT32 * ParentPrefix, + OUT UINT32 * SegCount + ) +{ + if ((Buffer =3D=3D NULL) || + (Root =3D=3D NULL) || + (ParentPrefix =3D=3D NULL) || + (SegCount =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *Root =3D 0; + *ParentPrefix =3D 0; + *SegCount =3D 0; + + // Handle Root and ParentPrefix(s). + if (*Buffer =3D=3D AML_ROOT_CHAR) { + *Root =3D 1; + Buffer++; + } else if (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR) { + do { + Buffer++; + (*ParentPrefix)++; + } while (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR); + } + + // Handle SegCount(s). + if (*Buffer =3D=3D AML_DUAL_NAME_PREFIX) { + *SegCount =3D 2; + } else if (*Buffer =3D=3D AML_MULTI_NAME_PREFIX) { + *SegCount =3D *((UINT8*)(Buffer + 1)); + } else if (AmlIsNameSeg (Buffer)) { + *SegCount =3D 1; + } else if (*Buffer =3D=3D AML_ZERO_OP) { + *SegCount =3D 0; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Safety checks on exit. + if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** Compute the ASL NameString/path size from NameString + information (Root, ParentPrefix, SegCount). + + @param [in] Root Number of root char. + Can be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Can be [0-255]. + @param [in] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @return Size of the ASL NameString/path. +**/ +UINT32 +EFIAPI +AslComputeNameStringSize ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ) +{ + UINT32 TotalSize; + + if (!AmlIsNameString (Root, ParentPrefix, SegCount)) { + ASSERT (0); + return 0; + } + + // Root and ParentPrefix(s). + TotalSize =3D Root + ParentPrefix; + + // Add size required for NameSeg(s). + TotalSize +=3D (SegCount * AML_NAME_SEG_SIZE); + + // Add size required for '.' separator(s). + TotalSize +=3D (SegCount > 1) ? (SegCount - 1) : 0; + + // Add 1 byte for NULL termination '\0'. + TotalSize +=3D 1; + + return TotalSize; +} + +/** Compute the AML NameString/path size from NameString + information (Root, ParentPrefix, SegCount). + + @param [in] Root Number of root char. + Can be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Can be [0-255]. + @param [in] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @return Size of the AML NameString/path. +**/ +UINT32 +EFIAPI +AmlComputeNameStringSize ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ) +{ + UINT32 TotalSize; + + if (!AmlIsNameString (Root, ParentPrefix, SegCount)) { + ASSERT (0); + return 0; + } + + // Root and ParentPrefix(s). + TotalSize =3D Root + ParentPrefix; + + // If SegCount =3D=3D 0, '\0' must end the AML NameString/path. + TotalSize +=3D (SegCount =3D=3D 0) ? 1 : (SegCount * AML_NAME_SEG_SIZE); + + // AML prefix. SegCount > 2 =3D MultiNamePrefix, SegCount =3D 2 DualName= Prefix. + TotalSize +=3D (SegCount > 2) ? 2 : ((SegCount =3D=3D 2) ? 1 : 0); + + return TotalSize; +} + +/** Get the ASL NameString/path size. + + @param [in] AslPath An ASL NameString/path. + @param [out] AslPathSizePtr Pointer holding the ASL NameString/path si= ze. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AslGetNameStringSize ( + IN CONST CHAR8 * AslPath, + OUT UINT32 * AslPathSizePtr + ) +{ + if ((AslPath =3D=3D NULL) || + (AslPathSizePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *AslPathSizePtr =3D 0; + do { + (*AslPathSizePtr)++; + AslPath++; + } while (*AslPath !=3D '\0'); + + return EFI_SUCCESS; +} + +/** Get the AML NameString/path size. + + @param [in] AmlPath An AML NameString/path. + @param [out] AmlPathSizePtr Pointer holding the AML NameString/path si= ze. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetNameStringSize ( + IN CONST CHAR8 * AmlPath, + OUT UINT32 * AmlPathSizePtr + ) +{ + EFI_STATUS Status; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if ((AmlPath =3D=3D NULL) || + (AmlPathSizePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlParseNameStringInfo ( + AmlPath, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + *AmlPathSizePtr =3D AmlComputeNameStringSize (Root, ParentPrefix, SegCou= nt); + if (*AmlPathSizePtr =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** Convert an ASL NameString/path to an AML NameString/path. + The caller must free the memory allocated in this function + for AmlPath using FreePool (). + + @param [in] AslPath An ASL NameString/path. + @param [out] OutAmlPath Buffer containing the AML path. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +ConvertAslNameToAmlName ( + IN CONST CHAR8 * AslPath, + OUT CHAR8 ** OutAmlPath + ) +{ + EFI_STATUS Status; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + UINT32 TotalSize; + UINT32 NameSegSize; + + CONST CHAR8 * AslBuffer; + CHAR8 * AmlBuffer; + CHAR8 * AmlPath; + + if ((AslPath =3D=3D NULL) || + (OutAmlPath =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Analyze AslPath. AslPath is checked in the call. + Status =3D AslParseNameStringInfo (AslPath, &Root, &ParentPrefix, &SegCo= unt); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Compute TotalSize. + TotalSize =3D AmlComputeNameStringSize (Root, ParentPrefix, SegCount); + if (TotalSize =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Allocate memory. + AmlPath =3D AllocateZeroPool (TotalSize); + if (AmlPath =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + AmlBuffer =3D AmlPath; + AslBuffer =3D AslPath; + + // Handle Root and ParentPrefix(s). + if (Root =3D=3D 1) { + *AmlBuffer =3D AML_ROOT_CHAR; + AmlBuffer++; + AslBuffer++; + } else if (ParentPrefix > 0) { + SetMem (AmlBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR); + AmlBuffer +=3D ParentPrefix; + AslBuffer +=3D ParentPrefix; + } + + // Handle prefix and SegCount(s). + if (SegCount > 2) { + *AmlBuffer =3D AML_MULTI_NAME_PREFIX; + AmlBuffer++; + *AmlBuffer =3D (UINT8)SegCount; + AmlBuffer++; + } else if (SegCount =3D=3D 2) { + *AmlBuffer =3D AML_DUAL_NAME_PREFIX; + AmlBuffer++; + } + + if (SegCount !=3D 0) { + // Write NameSeg(s). + while (1) { + SegCount--; + + // Get the NameSeg size. + if (!AslIsNameSeg (AslBuffer, &NameSegSize)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + + // Convert to Upper case and copy. + Status =3D AmlUpperCaseMemCpyS ( + AmlBuffer, + TotalSize, + AslBuffer, + NameSegSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Complete the NameSeg with an underscore ('_') if shorter than 4 b= ytes. + SetMem ( + AmlBuffer + NameSegSize, + AML_NAME_SEG_SIZE - NameSegSize, + AML_NAME_CHAR__ + ); + + // Go to the next NameSeg. + AmlBuffer +=3D AML_NAME_SEG_SIZE; + AslBuffer +=3D NameSegSize; + + // Skip the '.' separator. + if (SegCount !=3D 0) { + if (*AslBuffer =3D=3D '.') { + AslBuffer++; + } else { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + } else { + // (SegCount =3D=3D 0) + if (*AslBuffer =3D=3D '\0') { + break; + } else { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + } + } // while + + } else { + // (SegCount =3D=3D 0) + // '\0' needs to end the AML NameString/path. + *AmlBuffer =3D AML_ZERO_OP; + AmlBuffer++; + } + + // Safety checks on exit. + // Check that AmlPath has been filled with TotalSize bytes. + if ((SegCount !=3D 0) || + (*AslBuffer !=3D AML_ZERO_OP) || + (((UINT32)(AmlBuffer - AmlPath)) !=3D TotalSize)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + + *OutAmlPath =3D AmlPath; + return EFI_SUCCESS; + +error_handler: + FreePool (AmlPath); + return Status; +} + +/** Convert an AML NameString/path to an ASL NameString/path. + The caller must free the memory allocated in this function. + using FreePool (). + + @param [in] AmlPath An AML NameString/path. + @param [out] OutAslPath Buffer containing the ASL path. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +ConvertAmlNameToAslName ( + IN CONST CHAR8 * AmlPath, + OUT CHAR8 ** OutAslPath + ) +{ + EFI_STATUS Status; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + UINT32 TotalSize; + + CONST CHAR8 * AmlBuffer; + CHAR8 * AslBuffer; + CHAR8 * AslPath; + + if ((AmlPath =3D=3D NULL) || + (OutAslPath =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Analyze AslPath. AmlPath is checked in the call. + Status =3D AmlParseNameStringInfo (AmlPath, &Root, &ParentPrefix, &SegCo= unt); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Compute TotalSize. + TotalSize =3D AslComputeNameStringSize (Root, ParentPrefix, SegCount); + if (TotalSize =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Allocate memory. + AslPath =3D AllocateZeroPool (TotalSize); + if (AslPath =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + AmlBuffer =3D AmlPath; + AslBuffer =3D AslPath; + + // Handle prefix and SegCount(s). + if (Root =3D=3D 1) { + *AslBuffer =3D AML_ROOT_CHAR; + AslBuffer++; + AmlBuffer++; + } else if (ParentPrefix > 0) { + SetMem (AslBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR); + AslBuffer +=3D ParentPrefix; + AmlBuffer +=3D ParentPrefix; + } + + // Handle Root and Parent(s). + // Skip the MultiName or DualName prefix chars. + if (SegCount > 2) { + AmlBuffer +=3D 2; + } else if (SegCount =3D=3D 2) { + AmlBuffer +=3D 1; + } + + // Write NameSeg(s). + while (SegCount) { + // NameSeg is already in upper case and always 4 bytes long. + CopyMem (AslBuffer, AmlBuffer, AML_NAME_SEG_SIZE); + AslBuffer +=3D AML_NAME_SEG_SIZE; + AmlBuffer +=3D AML_NAME_SEG_SIZE; + + SegCount--; + + // Write the '.' separator if there is another NameSeg following. + if (SegCount !=3D 0) { + *AslBuffer =3D '.'; + AslBuffer++; + } + } // while + + // NULL terminate the ASL NameString. + *AslBuffer =3D '\0'; + AslBuffer++; + + // Safety checks on exit. + // Check that AslPath has been filled with TotalSize bytes. + if (((UINT32)(AslBuffer - AslPath)) !=3D TotalSize) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + + *OutAslPath =3D AslPath; + return EFI_SUCCESS; + +error_handler: + FreePool (AslPath); + return Status; +} + +/** Compare two ASL NameStrings. + + @param [in] AslName1 First NameString to compare. + @param [in] AslName2 Second NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +AslCompareNameString ( + IN CONST CHAR8 * AslName1, + IN CONST CHAR8 * AslName2 + ) +{ + EFI_STATUS Status; + UINT32 AslName1Len; + UINT32 AslName2Len; + + if ((AslName1 =3D=3D NULL) || + (AslName2 =3D=3D NULL)) { + ASSERT (0); + return FALSE; + } + + Status =3D AslGetNameStringSize (AslName1, &AslName1Len); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + Status =3D AslGetNameStringSize (AslName2, &AslName2Len); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // AslName1 and AslName2 don't have the same length + if (AslName1Len !=3D AslName2Len) { + return FALSE; + } + + return (CompareMem (AslName1, AslName2, AslName1Len) =3D=3D 0); +} + +/** Compare two AML NameStrings. + + @param [in] AmlName1 First NameString to compare. + @param [in] AmlName2 Second NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +AmlCompareNameString ( + IN CONST CHAR8 * AmlName1, + IN CONST CHAR8 * AmlName2 + ) +{ + EFI_STATUS Status; + UINT32 AmlName1Len; + UINT32 AmlName2Len; + + if ((AmlName1 =3D=3D NULL) || + (AmlName2 =3D=3D NULL)) { + ASSERT (0); + return FALSE; + } + + Status =3D AmlGetNameStringSize (AmlName1, &AmlName1Len); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + Status =3D AmlGetNameStringSize (AmlName2, &AmlName2Len); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // AmlName1 and AmlName2 don't have the same length + if (AmlName1Len !=3D AmlName2Len) { + return FALSE; + } + + return (CompareMem (AmlName1, AmlName2, AmlName1Len) =3D=3D 0); +} + +/** Compare an AML NameString and an ASL NameString. + + The ASL NameString is converted to an AML NameString before + being compared with the ASL NameString. This allows to expand + NameSegs shorter than 4 chars. + E.g.: AslName: "DEV" will be expanded to "DEV_" before being + compared. + + @param [in] AmlName1 AML NameString to compare. + @param [in] AslName2 ASL NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +CompareAmlWithAslNameString ( + IN CONST CHAR8 * AmlName1, + IN CONST CHAR8 * AslName2 + ) +{ + EFI_STATUS Status; + + CHAR8 * AmlName2; + BOOLEAN RetVal; + + if ((AmlName1 =3D=3D NULL) || + (AslName2 =3D=3D NULL)) { + ASSERT (0); + return FALSE; + } + + // Convert the AslName2 to an AmlName2. + // AmlName2 must be freed. + Status =3D ConvertAmlNameToAslName (AslName2, &AmlName2); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + RetVal =3D AmlCompareNameString (AmlName1, AmlName2); + + // Free AmlName2. + FreePool (AmlName2); + + return RetVal; +} +/** Given an AmlPath, return the address of the first NameSeg. + + It is possible to determine the size of an AML NameString/path just + by sight reading it. So no overflow can occur. + + @param [in] AmlPath The AML pathname. + @param [in] Root The AML pathname starts with a root char. + It is an absolute path. + @param [in] ParentPrefix The AML pathname has ParentPrefix + carets in its name. + + @return Pointer to the first NameSeg of the NameString. + Return NULL if AmlPath is NULL. +**/ +CONST +CHAR8 * +EFIAPI +AmlGetFirstNameSeg ( + IN CONST CHAR8 * AmlPath, + IN UINT32 Root, + IN UINT32 ParentPrefix + ) +{ + if (AmlPath =3D=3D NULL) { + ASSERT (0); + return NULL; + } + + AmlPath +=3D Root; + AmlPath +=3D ParentPrefix; + AmlPath +=3D ((*AmlPath =3D=3D AML_MULTI_NAME_PREFIX) ? 2 + : (*AmlPath =3D=3D AML_DUAL_NAME_PREFIX) ? 1 : 0); + return AmlPath; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h b/Dy= namicTablesPkg/Library/Common/AmlLib/String/AmlString.h new file mode 100644 index 0000000000000000000000000000000000000000..86d9df5f1918d57261c59f8df58= 5d5c80def3d41 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h @@ -0,0 +1,401 @@ +/** @file + AML String. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_STRING_H_ +#define AML_STRING_H_ + +/* This header file does not include internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions + must be included by the caller file. The function prototypes must + only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node + definitions. + This allows to keep the functions defined here both internal and + potentially external. If necessary, any function of this file can + be exposed externally. + The Api folder is internal to the AmlLib, but should only use these + functions. They provide a "safe" way to interact with the AmlLib. +*/ + +#include + +/** Check NameString/path information is valid. + + Root, ParentPrefix and SegCount cannot be 0 at the same time. + This function works for ASL and AML name strings. + + @param [in] Root Number of root char. + Must be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Must be [0-255]. + @param [in] SegCount Number of NameSeg (s). + Must be [0-255]. + + @retval TRUE id the input information is in the right boundaries. + FALSE otherwise. +**/ +BOOLEAN +EFIAPI +AmlIsNameString ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ); + +/** Copy bytes from SrcBuffer to DstBuffer and convert to upper case. + Don't copy more than MaxDstBufferSize bytes. + + @param [out] DstBuffer Destination buffer. + @param [in] MaxDstBufferSize Maximum size of DstBuffer. + Must be non-zero. + @param [in] SrcBuffer Source buffer. + @param [in] Count Count of bytes to copy from SrcBuffer. + Return success if 0. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpperCaseMemCpyS ( + OUT CHAR8 * DstBuffer, + IN UINT32 MaxDstBufferSize, + IN CONST CHAR8 * SrcBuffer, + IN UINT32 Count + ); + +/** Check whether Buffer is a root path ('\'). + + This function works for both ASL and AML pathnames. + Buffer must be at least 2 bytes long. + + @param [in] Buffer An ASL/AML path. + + @retval TRUE Buffer is a root path + @retval FALSE Buffer is not a root path. +**/ +BOOLEAN +EFIAPI +AmlIsRootPath ( + IN CONST CHAR8 * Buffer + ); + +/** Check whether Ch is an ASL/AML LeadName. + + This function works for both ASL and AML pathnames. + + ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms": + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + + ACPI 6.3 specification, s20.2.2. "Name Objects Encoding": + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + + @param [in] Ch The char to test. + + @retval TRUE Ch is an ASL/AML LeadName. + @retval FALSE Ch is not an ASL/AML LeadName. +**/ +BOOLEAN +EFIAPI +AmlIsLeadNameChar ( + IN CHAR8 Ch + ); + +/** Check whether Ch is an ASL/AML NameChar. + + This function works for both ASL and AML pathnames. + + ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms": + NameChar :=3D DigitChar | LeadNameChar + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + DigitChar :=3D '0'-'9' + + ACPI 6.3 specification, s20.2.2. "Name Objects Encoding": + NameChar :=3D DigitChar | LeadNameChar + LeadNameChar :=3D 'A'-'Z' | 'a'-'z' | '_' + DigitChar :=3D '0'-'9' + + @param [in] Ch The char to test. + + @retval TRUE Ch is an ASL/AML NameChar. + @retval FALSE Ch is not an ASL/AML NameChar. +**/ +BOOLEAN +EFIAPI +AmlIsNameChar ( + IN CHAR8 Ch + ); + +/** Check whether AslBuffer is an ASL NameSeg. + + This function only works for ASL NameStrings/pathnames. + ASL NameStrings/pathnames are at most 4 chars long. + + @param [in] AslBuffer Pointer in an ASL NameString/pathname. + @param [out] Size Size of the NameSeg. + + @retval TRUE AslBuffer is an ASL NameSeg. + @retval FALSE AslBuffer is not an ASL NameSeg. +**/ +BOOLEAN +EFIAPI +AslIsNameSeg ( + IN CONST CHAR8 * AslBuffer, + OUT UINT32 * Size + ); + +/** Check whether AmlBuffer is an AML NameSeg. + + This function only works for AML NameStrings/pathnames. + AML NameStrings/pathnames must be 4 chars long. + + @param [in] AmlBuffer Pointer in an AML NameString/pathname. + + @retval TRUE AmlBuffer is an AML NameSeg. + @retval FALSE AmlBuffer is not an AML NameSeg. +**/ +BOOLEAN +EFIAPI +AmlIsNameSeg ( + IN CONST CHAR8 * AmlBuffer + ); + +/** Parse an ASL NameString/path. + + An ASL NameString/path must be NULL terminated. + Information found in the ASL NameString/path is returned via pointers: + Root, ParentPrefix, SegCount. + + @param [in] Buffer ASL NameString/path. + @param [out] Root Pointer holding the number of root char. + Can be 0 or 1. + @param [out] ParentPrefix Pointer holding the number of carets char ('= ^'). + Can be [0-255]. + @param [out] SegCount Pointer holding the number of NameSeg (s). + Can be [0-255]. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AslParseNameStringInfo ( + IN CONST CHAR8 * Buffer, + OUT UINT32 * Root, + OUT UINT32 * ParentPrefix, + OUT UINT32 * SegCount + ); + +/** Parse an AML NameString/path. + + It is possible to determine the size of an AML NameString/path just + by sight reading it. So no overflow can occur. + Information found in the AML NameString/path is returned via pointers: + Root, ParentPrefix, SegCount. + + @param [in] Buffer AML NameString/path. + @param [out] Root Pointer holding the number of root char. + Can be 0 or 1. + @param [out] ParentPrefix Pointer holding the number of carets char = ('^'). + Can be [0-255]. + @param [out] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlParseNameStringInfo ( + IN CONST CHAR8 * Buffer, + OUT UINT32 * Root, + OUT UINT32 * ParentPrefix, + OUT UINT32 * SegCount + ); + +/** Compute the ASL NameString/path size from NameString + information (Root, ParentPrefix, SegCount). + + @param [in] Root Number of root char. + Can be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Can be [0-255]. + @param [in] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @return Size of the ASL NameString/path. +**/ +UINT32 +EFIAPI +AslComputeNameStringSize ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ); + +/** Compute the AML NameString/path size from NameString + information (Root, ParentPrefix, SegCount). + + @param [in] Root Number of root char. + Can be 0 or 1. + @param [in] ParentPrefix Number of carets char ('^'). + Can be [0-255]. + @param [in] SegCount Pointer holding the number of NameSeg(s). + Can be [0-255]. + + @return Size of the AML NameString/path. +**/ +UINT32 +EFIAPI +AmlComputeNameStringSize ( + IN UINT32 Root, + IN UINT32 ParentPrefix, + IN UINT32 SegCount + ); + +/** Get the ASL NameString/path size. + + @param [in] AslPath An ASL NameString/path. + @param [out] AslPathSizePtr Pointer holding the ASL NameString/path si= ze. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AslGetNameStringSize ( + IN CONST CHAR8 * AslPath, + OUT UINT32 * AslPathSizePtr + ); + +/** Get the AML NameString/path size. + + @param [in] AmlPath An AML NameString/path. + @param [out] AmlPathSizePtr Pointer holding the AML NameString/path si= ze. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetNameStringSize ( + IN CONST CHAR8 * AmlPath, + OUT UINT32 * AmlPathSizePtr + ); + +/** Convert an ASL NameString/path to an AML NameString/path. + The caller must free the memory allocated in this function + for AmlPath using FreePool (). + + @param [in] AslPath An ASL NameString/path. + @param [out] OutAmlPath Buffer containing the AML path. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +ConvertAslNameToAmlName ( + IN CONST CHAR8 * AslPath, + OUT CHAR8 ** OutAmlPath + ); + +/** Convert an AML NameString/path to an ASL NameString/path. + The caller must free the memory allocated in this function. + using FreePool (). + + @param [in] AmlPath An AML NameString/path. + @param [out] OutAslPath Buffer containing the ASL path. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +ConvertAmlNameToAslName ( + IN CONST CHAR8 * AmlPath, + OUT CHAR8 ** OutAslPath + ); + +/** Compare two ASL NameStrings. + + @param [in] AslName1 First NameString to compare. + @param [in] AslName2 Second NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +AslCompareNameString ( + IN CONST CHAR8 * AslName1, + IN CONST CHAR8 * AslName2 + ); + +/** Compare two AML NameStrings. + + @param [in] AmlName1 First NameString to compare. + @param [in] AmlName2 Second NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +AmlCompareNameString ( + IN CONST CHAR8 * AmlName1, + IN CONST CHAR8 * AmlName2 + ); + +/** Compare an AML NameString and an ASL NameString. + + The ASL NameString is converted to an AML NameString before + being compared with the ASL NameString. This allows to expand + NameSegs shorter than 4 chars. + E.g.: AslName: "DEV" will be expanded to "DEV_" before being + compared. + + @param [in] AmlName1 AML NameString to compare. + @param [in] AslName2 ASL NameString to compare. + + @retval TRUE if the two strings are identical. + @retval FALSE otherwise, or if error. +**/ +BOOLEAN +EFIAPI +CompareAmlWithAslNameString ( + IN CONST CHAR8 * AmlName1, + IN CONST CHAR8 * AslName2 + ); + +/** Given an AmlPath, return the address of the first NameSeg. + + It is possible to determine the size of an AML NameString/path just + by sight reading it. So no overflow can occur. + + @param [in] AmlPath The AML pathname. + @param [in] Root The AML pathname starts with a root char. + It is an absolute path. + @param [in] ParentPrefix The AML pathname has ParentPrefix + carets in its name. + + @return Pointer to the first NameSeg of the NameString. + Return NULL if AmlPath is NULL. +**/ +CONST +CHAR8 * +EFIAPI +AmlGetFirstNameSeg ( + IN CONST CHAR8 * AmlPath, + IN UINT32 Root, + IN UINT32 ParentPrefix + ); + +#endif // AML_STRING_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64091): https://edk2.groups.io/g/devel/message/64091 Mute This Topic: https://groups.io/mt/76149160/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64089+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245820467860.5578473827898; Wed, 12 Aug 2020 08:23:40 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id ETTkYY1788612xczHXLTP9HS; Wed, 12 Aug 2020 08:23:39 -0700 X-Received: from EUR03-DB5-obe.outbound.protection.outlook.com (EUR03-DB5-obe.outbound.protection.outlook.com [40.107.4.44]) by mx.groups.io with SMTP id smtpd.web10.17196.1597245814358514716 for ; Wed, 12 Aug 2020 08:23:35 -0700 X-Received: from AM6P195CA0091.EURP195.PROD.OUTLOOK.COM (2603:10a6:209:86::32) by VE1PR08MB5151.eurprd08.prod.outlook.com (2603:10a6:803:10c::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:86:cafe::70) by AM6P195CA0091.outlook.office365.com (2603:10a6:209:86::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64089+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT005.mail.protection.outlook.com (10.152.18.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: ("Tessian outbound 7a6fb63c1e64:v64"); Wed, 12 Aug 2020 15:23:31 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: f38f4c6e4407d59a X-CR-MTA-TID: 64aa7808 X-Received: from b5fbca6e867a.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id B00E488B-F61D-43A5-BFF9-626D3DBE5449.1; Wed, 12 Aug 2020 15:23:25 +0000 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id b5fbca6e867a.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:25 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dUsSryj6FEUWZH2yhEhTMXNERA2DrmVWiSHXaE2keDH1i8sTB0Y60tDkVPa6guQLaAVtfIaq0TLKhmrkV2a4WYarzeuCz97Goz2te+/fW6jwpRXqzRGdEK30LhYXP1MzxjsoQPLF1PbypmC528ok2pdm6rTtvnTkIIsrCo5DFHxxd/gGGQNeQ1aEDowb4INdZfSa7NN9IeC0kdvQwvTujsqdcSZZHVrScHdxOyWWLm0UQX6XWnurEfj5wd9H4uOtF+jPE/11XjDr7PePUCKF//AqDja5U8pIrRfWY+90BJQXEl1ZTfUaf7NY8G+LSrial+zlXv4YcmoZf/L8lxJzGg== 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-SenderADCheck; bh=OphA5OLRREQZKAVXUkYxDvhLQD0e6E5f6I/jwL0foS8=; b=bmak6hka57GmCqxrI7uP27OR+ThhDXFir0IdX8CG3IG8EPA4XVLm7yvJyxfvqJUeEvnKoRsbclwTaXTEMguZWCNKv/RQ56FTnxdwyiaUtEvtyJmcyaCi+sb1t1LLzlzj4kG0OmFGnJ+909nhb0NC3Da6yUDpw5RZHy7pn3Mnn2Zqtj/72JrRilIA4x7nrKcVe17bu7OK2AppqZkFDguMDdGycL0FPRYYWzKFpgV7M/skkfRCOa9ioiwUQi50Cg6UUMYNSl+nUOBxkXEt/4E1lbh4cbeDhGCTrTcLLpOr8iJ/bG6MmB8Zu9ZflbcdvaXHhl1MUvol+M1COcv+oDOglg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6P193CA0013.EURP193.PROD.OUTLOOK.COM (2603:10a6:6:29::23) by VI1PR08MB5407.eurprd08.prod.outlook.com (2603:10a6:803:132::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:23 +0000 X-Received: from DB5EUR03FT018.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:29:cafe::b) by DB6P193CA0013.outlook.office365.com (2603:10a6:6:29::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:23 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT018.mail.protection.outlook.com (10.152.20.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:23 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:21 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:20 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 12/30] DynamicTablesPkg: AML stream interface Date: Wed, 12 Aug 2020 16:22:18 +0100 Message-ID: <20200812152236.31164-13-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 075df24e-bab2-4df6-906f-08d83ed3abbe X-MS-TrafficTypeDiagnostic: VI1PR08MB5407:|VE1PR08MB5151: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4502;OLM:4502; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: ilNg5XM8PbqzK3DylyeDzVZYcdl+pHMtZ3cHFr0oHKKmtTYRIDCLWny2KbzXwizr0vRE8iI0JyHgtz038O6p424RrySnImoShY04+HYla19OL7gBVVHr3m1fSAUDxKosGVfqoXCgqFbxoWpCJOqckasd92GS4zbcsHp9cApfy0b0P6ioyP0oJDcJNso4XZgD/vV3mjTXm6+Wf0j0Kzsv6nQ1vSCItwipy/bo6OrAI6pgXPcAptXpr/PJJv7TAFVT8tuHwE0x3UuMlTSb7olOIA0g7rRWPxlNZev7bfN/TbavUq/UqpUQGUzYwB3tN5MK5gfcJrxdjSrQqtTUOqEDb51Ae/+0ju4XQfHIdqF2Ae+PdQw/jseziT8l3PUxPM89+Muw6gz/pc69fClVGT6mRA== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(346002)(396003)(39860400002)(136003)(376002)(46966005)(70206006)(70586007)(186003)(5660300002)(26005)(86362001)(316002)(7696005)(2616005)(54906003)(44832011)(1076003)(426003)(81166007)(336012)(47076004)(4326008)(30864003)(82310400002)(36756003)(8676002)(8936002)(83380400001)(478600001)(356005)(2906002)(6916009)(82740400003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB5407 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 63951dbe-df40-4c08-0986-08d83ed3a6fa X-Microsoft-Antispam-Message-Info: YDU61tV+ynzMlnjmRPU98rpCySQZYn849SHDFdOlVTTdqeE1Sky3hdeM/tiE5gLRBuvOrOglJSql/OugX0MeFBorUOY4gLOXu6syq9GdKO/Mp7ga6/+JgbwBdqoArWRIOZ9s7kwFNjUsoXEHYeX79EpmV3BBovG6rPxPq/l4AnlFofy7ByfxtggMuj87neYKeGgZto0hO19OgdsWvBWILDsWR9dzWDtV6RA1qSqAL2FxH/M3qbzlYroFBOObIJBc7gg3n6Cn1HfKTbPjHl+knOAKDQWZrMHFCjirhRhZFr1+aal+T6pPXjY2nSYLk5plIbxjKZS6DA/JDHQse+PgCq8v1zMnLslDMG7KBvtc0GiBxUL1NLmXIu8L0QFFbP6job+ZZE8/kFsfOqMXW7lDYg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:31.2216 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 075df24e-bab2-4df6-906f-08d83ed3abbe 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: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR08MB5151 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: kgYdo0Ix5cD6JjPgHTA4Z5Kbx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245819; bh=Cypki6LPDYP2lhtKADWtv4Ka/01v6D7zjd/vKWJ6XKQ=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=htY1nG6RlvOsBD166G8AcX3/C5s5hXEMPKZ17CB2K8Y236TgNOOukO6CdT+RtbGLPrN TJNnJLizan0pdWB/2DF2uwtWotDtTbE4EbZkABfnQtBXVCS7qgUToUKsRbwn6Mj+S/QF5 kr2Fpn6XGJF7jiNCnx3P8ktsjhi0/vGPyRg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Dynamic AML involves parsing/packing of AML opcode and data into AML byte streams. The AML stream interface provides safe buffer management as well as supports forward and reverse streams. It provides functions to create, read, write, clone and compare AML streams. Co-authored-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c | 665 ++++++++++= ++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h | 451 ++++++++++= +++ 2 files changed, 1116 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c b/Dy= namicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c new file mode 100644 index 0000000000000000000000000000000000000000..419e796e50cbe29e62234916c6e= 39c2c625a2951 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c @@ -0,0 +1,665 @@ +/** @file + AML Stream. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +/** Initialize a stream. + + @param [in, out] Stream Pointer to the stream to initialize. + @param [in] Buffer Buffer to initialize Stream with. + Point to the beginning of the Buffer. + @param [in] MaxBufferSize Maximum size of Buffer. + @param [in] Direction Direction Stream is progressing + (forward, backward). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamInit ( + IN OUT AML_STREAM * Stream, + IN UINT8 * Buffer, + IN UINT32 MaxBufferSize, + IN EAML_STREAM_DIRECTION Direction + ) +{ + if ((Stream =3D=3D NULL) || + (Buffer =3D=3D NULL) || + (MaxBufferSize =3D=3D 0) || + ((Direction !=3D EAmlStreamDirectionForward) && + (Direction !=3D EAmlStreamDirectionBackward))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream->Buffer =3D Buffer; + Stream->MaxBufferSize =3D MaxBufferSize; + Stream->Index =3D 0; + Stream->Direction =3D Direction; + + return EFI_SUCCESS; +} + +/** Clone a stream. + + Cloning a stream means copying all the values of the input Stream + in the ClonedStream. + + @param [in] Stream Pointer to the stream to clone. + @param [in] ClonedStream Pointer to the stream to initialize. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamClone ( + IN CONST AML_STREAM * Stream, + OUT AML_STREAM * ClonedStream + ) +{ + if (!IS_STREAM (Stream) || + (ClonedStream =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ClonedStream->Buffer =3D Stream->Buffer; + ClonedStream->MaxBufferSize =3D Stream->MaxBufferSize; + ClonedStream->Index =3D Stream->Index; + ClonedStream->Direction =3D Stream->Direction; + + return EFI_SUCCESS; +} + +/** Initialize a sub-stream from a stream. + + A sub-stream is a stream initialized at the current position of the input + stream: + - the Buffer field points to the current position of the input stream; + - the Index field is set to 0; + - the MaxBufferSize field is set to the remaining size of the input st= ream; + - the direction is conserved; + + E.g.: For a forward stream: + +----------------+----------------+ + |ABCD.........XYZ| Free Space | + +----------------+----------------+ + ^ ^ ^ + Stream: Buffer CurrPos EndOfBuff + Sub-stream: Buffer/CurrPos EndOfBuff + + @param [in] Stream Pointer to the stream from which a sub-stream = is + created. + @param [in] SubStream Pointer to the stream to initialize. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamInitSubStream ( + IN CONST AML_STREAM * Stream, + OUT AML_STREAM * SubStream + ) +{ + if (!IS_STREAM (Stream) || + (SubStream =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (IS_STREAM_FORWARD (Stream)) { + SubStream->Buffer =3D AmlStreamGetCurrPos (Stream); + } else if (IS_STREAM_BACKWARD (Stream)) { + SubStream->Buffer =3D Stream->Buffer; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + SubStream->MaxBufferSize =3D AmlStreamGetFreeSpace (Stream); + SubStream->Index =3D 0; + SubStream->Direction =3D Stream->Direction; + + return EFI_SUCCESS; +} + +/** Get the buffer of a stream. + + @param [in] Stream Pointer to a stream. + + @return The stream's Buffer. + NULL otherwise. +**/ +UINT8 * +EFIAPI +AmlStreamGetBuffer ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return NULL; + } + return Stream->Buffer; +} + +/** Get the size of Stream's Buffer. + + @param [in] Stream Pointer to a stream. + + @return The Size of Stream's Buffer. + Return 0 if Stream is invalid. +**/ +UINT32 +EFIAPI +AmlStreamGetMaxBufferSize ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return 0; + } + return Stream->MaxBufferSize; +} + +/** Reduce the maximal size of Stream's Buffer (MaxBufferSize field). + + @param [in] Stream Pointer to a stream. + @param [in] Diff Value to subtract to the Stream's MaxBufferSize. + 0 < x < MaxBufferSize - Index. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamReduceMaxBufferSize ( + IN AML_STREAM * Stream, + IN UINT32 Diff + ) +{ + if (!IS_STREAM (Stream) || + (Diff =3D=3D 0) || + ((Stream->MaxBufferSize - Diff) <=3D Stream->Index)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream->MaxBufferSize -=3D Diff; + return EFI_SUCCESS; +} + +/** Get Stream's Index. + + Stream's Index is incremented when writing data, reading data, + or moving the position in the Stream. + It can be seen as an index: + - starting at the beginning of Stream's Buffer if the stream goes forwa= rd; + - starting at the end of Stream's Buffer if the stream goes backward. + + @param [in] Stream Pointer to a stream. + + @return Stream's Index. + Return 0 if Stream is invalid. +**/ +UINT32 +EFIAPI +AmlStreamGetIndex ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return 0; + } + return Stream->Index; +} + +/** Get Stream's Direction. + + @param [in] Stream Pointer to a stream. + + @return Stream's Direction. + Return EAmlStreamDirectionUnknown if Stream is invalid. +**/ +EAML_STREAM_DIRECTION +EFIAPI +AmlStreamGetDirection ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return EAmlStreamDirectionInvalid; + } + return Stream->Direction; +} + +/** Return a pointer to the current position in the stream. + + @param [in] Stream Pointer to a stream. + + @return The current position in the stream. + Return NULL if error. +**/ +UINT8 * +EFIAPI +AmlStreamGetCurrPos ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return NULL; + } + + if (IS_STREAM_FORWARD (Stream)) { + return Stream->Buffer + Stream->Index; + } else if (IS_STREAM_BACKWARD (Stream)) { + return Stream->Buffer + (Stream->MaxBufferSize - 1) - Stream->Index; + } else { + ASSERT (0); + return NULL; + } +} + +/** Get the space available in the stream. + + @param [in] Stream Pointer to a stream. + + @return Remaining space available in the stream. + Zero in case of error or if the stream is at its end. +**/ +UINT32 +EFIAPI +AmlStreamGetFreeSpace ( + IN CONST AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return 0; + } + + if (Stream->Index > Stream->MaxBufferSize) { + ASSERT (0); + return 0; + } + + return Stream->MaxBufferSize - Stream->Index; +} + +/** Move Stream by Offset bytes. + + The stream current position is moved according to the stream direction + (forward, backward). + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [in] Offset Offset to move the stream of. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamProgress ( + IN AML_STREAM * Stream, + IN UINT32 Offset + ) +{ + if (!IS_STREAM (Stream) || + IS_END_OF_STREAM (Stream) || + (Offset =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (AmlStreamGetFreeSpace (Stream) < Offset) { + ASSERT (0); + return EFI_BUFFER_TOO_SMALL; + } + + Stream->Index +=3D Offset; + + return EFI_SUCCESS; +} + +/** Rewind Stream of Offset bytes. + + The stream current position is rewound according to the stream direction + (forward, backward). A stream going forward will be rewound backward. + + @param [in] Stream Pointer to a stream. + @param [in] Offset Offset to rewind the stream of. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamRewind ( + IN AML_STREAM * Stream, + IN UINT32 Offset + ) +{ + if (!IS_STREAM (Stream) || + (Offset =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (AmlStreamGetIndex (Stream) < Offset) { + ASSERT (0); + return EFI_BUFFER_TOO_SMALL; + } + + Stream->Index -=3D Offset; + + return EFI_SUCCESS; +} + +/** Reset the Stream (move the current position to the initial position). + + @param [in] Stream Pointer to a stream. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamReset ( + IN AML_STREAM * Stream + ) +{ + if (!IS_STREAM (Stream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream->Index =3D 0; + + return EFI_SUCCESS; +} + +/** Peek one byte at Stream's current position. + + Stream's position is not moved when peeking. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [out] OutByte Pointer holding the byte value of + the stream current position. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamPeekByte ( + IN AML_STREAM * Stream, + OUT UINT8 * OutByte + ) +{ + UINT8 * CurPos; + + if (!IS_STREAM (Stream) || + IS_END_OF_STREAM (Stream) || + (OutByte =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CurPos =3D AmlStreamGetCurrPos (Stream); + if (CurPos =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutByte =3D *CurPos; + return EFI_SUCCESS; +} + +/** Read one byte at Stream's current position. + + The stream current position is moved when reading. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [out] OutByte Pointer holding the byte value of + the stream current position. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamReadByte ( + IN AML_STREAM * Stream, + OUT UINT8 * OutByte + ) +{ + EFI_STATUS Status; + + if (!IS_STREAM (Stream) || + IS_END_OF_STREAM (Stream) || + (OutByte =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Stream is checked in the function call. + Status =3D AmlStreamPeekByte (Stream, OutByte); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlStreamProgress (Stream, 1); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Write Size bytes in the stream. + + If the stream goes backward (toward lower addresses), the bytes written + to the stream are not reverted. + In the example below, writing "Hello" to the stream will not revert + the string. The end of the stream buffer will contain "Hello world!". + Stream buffer: + +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' | + +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + ^ + Current position. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [in] Buffer Pointer to the data to write. + @param [in] Size Number of bytes to write. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamWrite ( + IN AML_STREAM * Stream, + IN CONST UINT8 * Buffer, + IN UINT32 Size + ) +{ + UINT8 * CurrPos; + + if (!IS_STREAM (Stream) || + IS_END_OF_STREAM (Stream) || + (Buffer =3D=3D NULL) || + (Size =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (AmlStreamGetFreeSpace (Stream) < Size) { + ASSERT (0); + return EFI_BUFFER_TOO_SMALL; + } + + CurrPos =3D AmlStreamGetCurrPos (Stream); + + // If the Stream goes backward, prepare some space to copy the data. + if (IS_STREAM_BACKWARD (Stream)) { + CurrPos -=3D Size; + } + + CopyMem (CurrPos, Buffer, Size); + Stream->Index +=3D Size; + + return EFI_SUCCESS; +} + +/** Compare Size bytes between Stream1 and Stream2 from their + respective current position. + + Stream1 and Stream2 must go in the same direction. + Stream1 and Stream2 are left unchanged. + + @param [in] Stream1 First stream to compare. + The stream must not be at its end. + @param [in] Stream2 Second stream to compare. + The stream must not be at its end. + @param [in] Size Number of bytes to compare. + Must be lower than the minimum remaining space of + Stream1 and Stream2. + Must be non-zero. + + @retval TRUE If Stream1 and Stream2 have Size bytes equal, + from their respective current position. + The function completed successfully. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlStreamCmp ( + IN CONST AML_STREAM * Stream1, + IN CONST AML_STREAM * Stream2, + IN UINT32 Size + ) +{ + UINT32 MinSize; + UINT8 * CurrPosStream1; + UINT8 * CurrPosStream2; + + if (!IS_STREAM (Stream1) || + IS_END_OF_STREAM (Stream1) || + !IS_STREAM (Stream2) || + IS_END_OF_STREAM (Stream2) || + (Stream1->Direction !=3D Stream2->Direction) || + (Size =3D=3D 0)) { + ASSERT (0); + return FALSE; + } + + // Check the Size is not longer than the remaining size of + // Stream1 and Stream2. + MinSize =3D MIN ( + AmlStreamGetFreeSpace (Stream1), + AmlStreamGetFreeSpace (Stream2) + ); + if (MinSize < Size) { + ASSERT (0); + return FALSE; + } + + CurrPosStream1 =3D AmlStreamGetCurrPos (Stream1); + if (CurrPosStream1 =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + CurrPosStream2 =3D AmlStreamGetCurrPos (Stream2); + if (CurrPosStream2 =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + if (Stream1->Direction =3D=3D EAmlStreamDirectionForward) { + return (0 =3D=3D CompareMem (CurrPosStream1, CurrPosStream2, MinSize)); + } + + // The stream is already pointing on the last byte, thus the (-1). + // +---------------------+ + // BStream | | | | | | | |M|E|T|0| + // +---------------------+ + // ^ + // CurrPos + return (0 =3D=3D CompareMem ( + CurrPosStream1 - (MinSize - 1), + CurrPosStream2 - (MinSize - 1), + MinSize + )); +} + +/** Copy Size bytes of the stream's data to DstBuffer. + + For a backward stream, the bytes are copied starting from the + current stream position. + + @param [out] DstBuffer Destination Buffer to copy the data to. + @param [in] MaxDstBufferSize Maximum size of DstBuffer. + Must be non-zero. + @param [in] Stream Pointer to the stream to copy the data f= rom. + @param [in] Size Number of bytes to copy from the stream + buffer. + Must be lower than MaxDstBufferSize. + Must be lower than Stream's MaxBufferSiz= e. + Return success if zero. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamCpyS ( + OUT CHAR8 * DstBuffer, + IN UINT32 MaxDstBufferSize, + IN AML_STREAM * Stream, + IN UINT32 Size + ) +{ + CHAR8 * StreamBufferStart; + + // Stream is checked in the function call. + if ((DstBuffer =3D=3D NULL) || + (MaxDstBufferSize =3D=3D 0) || + (Size > MaxDstBufferSize) || + (Size > AmlStreamGetMaxBufferSize (Stream))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (Size =3D=3D 0) { + return EFI_SUCCESS; + } + + // Find the address at which the data is starting. + StreamBufferStart =3D (CHAR8*)(IS_STREAM_FORWARD (Stream) ? + Stream->Buffer : + AmlStreamGetCurrPos (Stream)); + + CopyMem (DstBuffer, StreamBufferStart, Size); + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h b/Dy= namicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h new file mode 100644 index 0000000000000000000000000000000000000000..cd2da89b072bd38f5c191f9ef35= 753b445b3f83d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h @@ -0,0 +1,451 @@ +/** @file + AML Stream. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_STREAM_H_ +#define AML_STREAM_H_ + +#include + +/** Stream direction. + + Enum to choose the direction the stream is progressing. +*/ +typedef enum EAmlStreamDirection { + EAmlStreamDirectionInvalid, ///< Invalid AML Stream direction. + EAmlStreamDirectionForward, ///< Forward direction. + /// The Stream goes toward higher addre= sses. + EAmlStreamDirectionBackward, ///< Forward direction. + /// The Stream goes toward lower addres= ses. + EAmlStreamDirectionMax, ///< Max enum. +} EAML_STREAM_DIRECTION; + +/** Stream. + + This structure is used as a wrapper around a buffer. It allows to do com= mon + buffer manipulations (read, write, etc.) while preventing buffer overflo= ws. +*/ +typedef struct AmlStream { + /// Pointer to a buffer. + UINT8 * Buffer; + + /// Size of Buffer. + UINT32 MaxBufferSize; + + /// Index in the Buffer. + /// The Index field allows to keep track of how many bytes have been + /// read/written in the Buffer, and to retrieve the current stream posit= ion. + /// 0 <=3D Index <=3D MaxBufferSize. + /// If Index =3D=3D MaxBufferSize, no more action is allowed on the stre= am. + UINT32 Index; + + /// The direction the stream is progressing. + /// If the stream goes backward (toward lower addresses), the bytes writ= ten + /// to the stream are not reverted. + /// In the example below, writing "Hello" to the stream will not revert + /// the string. The end of the stream buffer will contain "Hello world!". + /// Similarly, moving the stream position will be done according to the + /// direction of the stream. + /// Stream buffer: + /// +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + /// |-------------- | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' | + /// +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + /// ^ + /// Current position. + EAML_STREAM_DIRECTION Direction; +} AML_STREAM; + +/** Check whether a StreamPtr is a valid Stream. + + @param [in] Stream Pointer to a stream. + + @retval TRUE Stream is a pointer to a stream. + @retval FALSE Otherwise. +*/ +#define IS_STREAM(Stream) ( = \ + (((AML_STREAM*)Stream) !=3D NULL) = && \ + (((AML_STREAM*)Stream)->Buffer !=3D NULL)) + +/** Check whether a Stream is at the end of its buffer. + + @param [in] Stream Pointer to a stream. + + @retval TRUE Stream is a pointer to a non-full stream. + @retval FALSE Otherwise. +*/ +#define IS_END_OF_STREAM(Stream) ( = \ + (((AML_STREAM*)Stream)->Index =3D=3D = \ + ((AML_STREAM*)Stream)->MaxBufferSize)) + +/** Check Stream goes forward. + + @param [in] Stream Pointer to a stream. + + @retval TRUE Stream goes forward. + @retval FALSE Otherwise. +*/ +#define IS_STREAM_FORWARD(Stream) ( = \ + ((AML_STREAM*)Stream)->Direction =3D=3D EAmlStreamDirectionForward) + +/** Check Stream goes backward. + + @param [in] Stream Pointer to a stream. + + @retval TRUE Stream goes backward. + @retval FALSE Otherwise. +*/ +#define IS_STREAM_BACKWARD(Stream) ( = \ + ((AML_STREAM*)Stream)->Direction =3D=3D EAmlStreamDirectionBackward) + +/** Initialize a stream. + + @param [in, out] Stream Pointer to the stream to initialize. + @param [in] Buffer Buffer to initialize Stream with. + Point to the beginning of the Buffer. + @param [in] MaxBufferSize Maximum size of Buffer. + @param [in] Direction Direction Stream is progressing + (forward, backward). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamInit ( + IN OUT AML_STREAM * Stream, + IN UINT8 * Buffer, + IN UINT32 MaxBufferSize, + IN EAML_STREAM_DIRECTION Direction + ); + +/** Clone a stream. + + Cloning a stream means copying all the values of the input Stream + in the ClonedStream. + + @param [in] Stream Pointer to the stream to clone. + @param [in] ClonedStream Pointer to the stream to initialize. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamClone ( + IN CONST AML_STREAM * Stream, + OUT AML_STREAM * ClonedStream + ); + +/** Initialize a sub-stream from a stream. + + A sub-stream is a stream initialized at the current position of the input + stream: + - the Buffer field points to the current position of the input stream; + - the Index field is set to 0; + - the MaxBufferSize field is set to the remaining size of the input st= ream; + - the direction is conserved; + + E.g.: For a forward stream: + +----------------+----------------+ + |ABCD.........XYZ| Free Space | + +----------------+----------------+ + ^ ^ ^ + Stream: Buffer CurrPos EndOfBuff + Sub-stream: Buffer/CurrPos EndOfBuff + + @param [in] Stream Pointer to the stream from which a sub-stream = is + created. + @param [in] SubStream Pointer to the stream to initialize. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamInitSubStream ( + IN CONST AML_STREAM * Stream, + OUT AML_STREAM * SubStream + ); + +/** Get the buffer of a stream. + + @param [in] Stream Pointer to a stream. + + @return The stream's Buffer. + NULL otherwise. +**/ +UINT8 * +EFIAPI +AmlStreamGetBuffer ( + IN CONST AML_STREAM * Stream + ); + +/** Get the size of Stream's Buffer. + + @param [in] Stream Pointer to a stream. + + @return The Size of Stream's Buffer. + Return 0 if Stream is invalid. +**/ +UINT32 +EFIAPI +AmlStreamGetMaxBufferSize ( + IN CONST AML_STREAM * Stream + ); + +/** Reduce the maximal size of Stream's Buffer (MaxBufferSize field). + + @param [in] Stream Pointer to a stream. + @param [in] Diff Value to subtract to the Stream's MaxBufferSize. + 0 < x < MaxBufferSize - Index. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamReduceMaxBufferSize ( + IN AML_STREAM * Stream, + IN UINT32 Diff + ); + +/** Get Stream's Index. + + Stream's Index is incremented when writing data, reading data, + or moving the position in the Stream. + It can be seen as an index: + - starting at the beginning of Stream's Buffer if the stream goes forwa= rd; + - starting at the end of Stream's Buffer if the stream goes backward. + + @param [in] Stream Pointer to a stream. + + @return Stream's Index. + Return 0 if Stream is invalid. +**/ +UINT32 +EFIAPI +AmlStreamGetIndex ( + IN CONST AML_STREAM * Stream + ); + +/** Get Stream's Direction. + + @param [in] Stream Pointer to a stream. + + @return Stream's Direction. + Return EAmlStreamDirectionUnknown if Stream is invalid. +**/ +EAML_STREAM_DIRECTION +EFIAPI +AmlStreamGetDirection ( + IN CONST AML_STREAM * Stream + ); + +/** Return a pointer to the current position in the stream. + + @param [in] Stream Pointer to a stream. + + @return The current position in the stream. + Return NULL if error. +**/ +UINT8 * +EFIAPI +AmlStreamGetCurrPos ( + IN CONST AML_STREAM * Stream + ); + +/** Get the space available in the stream. + + @param [in] Stream Pointer to a stream. + + @return Remaining space available in the stream. + Zero in case of error or if the stream is at its end. +**/ +UINT32 +EFIAPI +AmlStreamGetFreeSpace ( + IN CONST AML_STREAM * Stream + ); + +/** Move Stream by Offset bytes. + + The stream current position is moved according to the stream direction + (forward, backward). + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [in] Offset Offset to move the stream of. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamProgress ( + IN AML_STREAM * Stream, + IN UINT32 Offset + ); + +/** Rewind Stream of Offset bytes. + + The stream current position is rewound according to the stream direction + (forward, backward). A stream going forward will be rewound backward. + + @param [in] Stream Pointer to a stream. + @param [in] Offset Offset to rewind the stream of. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamRewind ( + IN AML_STREAM * Stream, + IN UINT32 Offset + ); + +/** Reset the Stream (move the current position to the initial position). + + @param [in] Stream Pointer to a stream. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamReset ( + IN AML_STREAM * Stream + ); + +/** Peek one byte at Stream's current position. + + Stream's position is not moved when peeking. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [out] OutByte Pointer holding the byte value of + the stream current position. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamPeekByte ( + IN AML_STREAM * Stream, + OUT UINT8 * OutByte + ); + +/** Read one byte at Stream's current position. + + The stream current position is moved when reading. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [out] OutByte Pointer holding the byte value of + the stream current position. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamReadByte ( + IN AML_STREAM * Stream, + OUT UINT8 * OutByte + ); + +/** Write Size bytes in the stream. + + If the stream goes backward (toward lower addresses), the bytes written + to the stream are not reverted. + In the example below, writing "Hello" to the stream will not revert + the string. The end of the stream buffer will contain "Hello world!". + Stream buffer: + +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' | + +---------------+-----+-----+-----+-----+-----+-----+---- +------+ + ^ + Current position. + + @param [in] Stream Pointer to a stream. + The stream must not be at its end. + @param [in] Buffer Pointer to the data to write. + @param [in] Size Number of bytes to write. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlStreamWrite ( + IN AML_STREAM * Stream, + IN CONST UINT8 * Buffer, + IN UINT32 Size + ); + +/** Compare Size bytes between Stream1 and Stream2 from their + respective current position. + + Stream1 and Stream2 must go in the same direction. + Stream1 and Stream2 are left unchanged. + + @param [in] Stream1 First stream to compare. + The stream must not be at its end. + @param [in] Stream2 Second stream to compare. + The stream must not be at its end. + @param [in] Size Number of bytes to compare. + Must be lower than the minimum remaining space of + Stream1 and Stream2. + Must be non-zero. + + @retval TRUE If Stream1 and Stream2 have Size bytes equal, + from their respective current position. + The function completed successfully. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlStreamCmp ( + IN CONST AML_STREAM * Stream1, + IN CONST AML_STREAM * Stream2, + IN UINT32 Size + ); + +/** Copy Size bytes of the stream's data to DstBuffer. + + For a backward stream, the bytes are copied starting from the + current stream position. + + @param [out] DstBuffer Destination Buffer to copy the data to. + @param [in] MaxDstBufferSize Maximum size of DstBuffer. + Must be non-zero. + @param [in] Stream Pointer to the stream to copy the data f= rom. + @param [in] Size Number of bytes to copy from the stream + buffer. + Must be lower than MaxDstBufferSize. + Must be lower than Stream's MaxBufferSiz= e. + Return success if zero. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlStreamCpyS ( + OUT CHAR8 * DstBuffer, + IN UINT32 MaxDstBufferSize, + IN AML_STREAM * Stream, + IN UINT32 Size + ); + +#endif // AML_STREAM_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64089): https://edk2.groups.io/g/devel/message/64089 Mute This Topic: https://groups.io/mt/76149157/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64090+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245821970571.2540348340966; Wed, 12 Aug 2020 08:23:41 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id r4WaYY1788612xFH8Ntm0VE3; Wed, 12 Aug 2020 08:23:40 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.55]) by mx.groups.io with SMTP id smtpd.web11.17175.1597245814818363344 for ; Wed, 12 Aug 2020 08:23:35 -0700 X-Received: from AM5P194CA0023.EURP194.PROD.OUTLOOK.COM (2603:10a6:203:8f::33) by DBBPR08MB4425.eurprd08.prod.outlook.com (2603:10a6:10:cc::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:8f:cafe::e5) by AM5P194CA0023.outlook.office365.com (2603:10a6:203:8f::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64090+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT044.mail.protection.outlook.com (10.152.19.106) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:30 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: a752c14dc4ed07a7 X-CR-MTA-TID: 64aa7808 X-Received: from a4fffb865fb6.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 41D774C2-4A5C-45CA-892E-7409C0292015.1; Wed, 12 Aug 2020 15:23:25 +0000 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id a4fffb865fb6.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:25 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=f8bm70BUNNZ8cjHagfVs5IoN1uZEN8dRhCOs4mXhyjGSO1FcIDiLIzATh00YBEhtp8KjZ3aHiaVgT2PevNHUcGBd49YTy+03rVbD1C64D92dcEhb+GlxMzJH5Ep456uUOoQ4oesNoxKKR86x3o8FQDAXTuUI6PmqzIdeDbLbXynngysVnzw3uFSi63M74GJyHzARP5PwxynHcV85u1AdpSkHOlHb/rKhlSl1Fx+ToiIJO+rgPBdBnmLQxEMr2lrCBJAmkC7H8c1UdmtcNEJYG2K+W1ztg0Dx3UrE9Z1Uss9O/lgcwjHUeDDHDEfgqAWOi7jsKLblNawwOUFXVyhKPw== 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-SenderADCheck; bh=k/oYY8eNZsVHxDRYVgfp5/qjKLTEfvOJhuQS0SNB6VA=; b=cyIHKsImlQPYY7yCYTFiA2ZbxDB4tvnobQM00IHQYBw/teIt23bQK8UcCS0Q5BmmXie+/8NNgzNNYbrQ/b+AxYm1AbFu7BvcvscnDmzu/ohm3h7rDonfTxHuvrU/KmVT35HGBFBfl9LPgHmKYDxqI2Gw/LF/ofDdUYTcjPMlYpL7Zi9XN3dGYCmp6REqXF7XIFCZCDzuw23m1p7sJarH76btC4dDxOn0ctJONbc4cFK/XAPEtK+8qVHq4POaxuUl8gy4TAoCgEX9+9SVAB+60bBjyU2JkR1RC8VPzBBDMd9aXQBWHLq1YBX27SOZgZUb8iPOiNYKRzjK0gjuSF+egg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM5PR0602CA0011.eurprd06.prod.outlook.com (2603:10a6:203:a3::21) by DB8PR08MB5514.eurprd08.prod.outlook.com (2603:10a6:10:fa::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from AM5EUR03FT011.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:a3:cafe::c8) by AM5PR0602CA0011.outlook.office365.com (2603:10a6:203:a3::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:24 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT011.mail.protection.outlook.com (10.152.16.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:22 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:22 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 13/30] DynamicTablesPkg: AML serialise interface Date: Wed, 12 Aug 2020 16:22:19 +0100 Message-ID: <20200812152236.31164-14-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2f79708c-32c3-43e0-4ee7-08d83ed3aba9 X-MS-TrafficTypeDiagnostic: DB8PR08MB5514:|DBBPR08MB4425: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4125;OLM:4125; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: r8TRaMKFyV5N0+ZMWD+DblR542UZCfbcao3a2aZIErMpTXDEQceGhHaTOdW6yw6CdGsX3Gr++2YRBVnIHcpyQ4sWO4IcWnQ8s+mP62s9FvpH/PyBeszKjT6vZOXSNgXNlScbtdBwo93pQiSgBibZ6cWf6J60FgIxp3YEiN9+Iri8e3iiP3WroQ33ji3muMqESzjV2TtdU0l+QQz8SXd5iFHBF0pH6z8VyTG9IBklKbuGwSdNqNl7bUF0IEoC410wugvxxuHhSqItbW/ovMIBCMRw5GQnOUDhQT+XqzWgccx+u4GBQTJgRE39jFH5XvJokTbn//GHpAsBquBm6upyzcif5krRHY3kkTpvMhyQ9jHbPlq+AD+EQAqR21c26n8Q7lQDg/UywWw0BkQ9/UeHdA== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(396003)(346002)(376002)(136003)(39860400002)(46966005)(36756003)(81166007)(44832011)(86362001)(54906003)(5660300002)(82310400002)(2906002)(426003)(6666004)(1076003)(2616005)(26005)(8936002)(8676002)(7696005)(4326008)(186003)(336012)(356005)(70206006)(316002)(83380400001)(82740400003)(478600001)(70586007)(6916009)(47076004);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB5514 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 6b768dcd-8506-4335-2931-08d83ed3a7b6 X-Microsoft-Antispam-Message-Info: ETVoDEX9gzttYSoqGuxG4a6w5q1fLoMFt9KtCrGaG+UsbGcxSgdtt0J9fo8J3StAB6+JKtbHESiQd1407222gjKca0fQoHFJ+qtN9/SFIbSzgh7AD4RKpKXYmsGf0A6EWK60WBAAD5S5iv9KdOnwa5jtwN/dVPcJ/LZFBw0TiGBjmTg1rOeNHdBHTb4O+RT+17rFy8wSgNBHi9OQUgFbep1bTC1FnSFOFu7Amr/qm1aIjoT1tjGnzSB098BJEp7Ebou8CSiFz7WQsWCiHdJgyYrblyCK6yCZ4gvhAQF849Wz3fm7xgmrdPyjrmKTpRax5ryJiSkrXcclnQXnXFv9dHQIRfEg4NUhJYfQNo2D05Jj6mq82SJtY8CzPza0vT0uRyGvDRtWIQKpmnQgb5lATA== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:31.0833 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 2f79708c-32c3-43e0-4ee7-08d83ed3aba9 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: VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4425 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: bVeso0vsnGNoAfUY7UuCYH1cx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245820; bh=QcdW+PQJnfh4AQv6LD5IgpTjtGFxI/ZFlmBCZPukzqY=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=uE/4xbKQ02q76ITPcnory3g6q1ZTOOwQYnq8Mb7tl0DO3UFowBDKTkul4gksPmLTDzF WlNqHdh/WPBhHGX47WBPu0yi/kkh0LT/NpHcj8oZ/9r2YbmNJzTwUyXlDmgdkyJeJUCtW vGBH6MjfFusVYmU0RCWEBqFDpvRpI6rrc3Q= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML Fixup and AML Codegen facilitate dynamic generation of Definition Block tables. The AML byte stream that is generated is represented in an AML tree. Once the AML table generation is completed, the AML tree needs to be serialised for installing as an ACPI table. The AML serialise interface implements the functionality to iterate the nodes in the AML tree, collating the AML bytecode, computing the checksum and writing the AML byte stream to a buffer that represents the Definition Block table. Signed-off-by: Pierre Gondois Co-authored-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c | 324 ++++= ++++++++++++++++ 1 file changed, 324 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.= c b/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c new file mode 100644 index 0000000000000000000000000000000000000000..2a47c229d7480128ed0f782efa0= 09c7a86f4a492 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c @@ -0,0 +1,324 @@ +/** @file + AML Serialize. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include + +/** Callback function to copy the AML bytecodes contained in a node + to the Stream stored in the Context. + The SDT header data contained in the root node is not serialized + by this function. + + @param [in] Node Pointer to the node to copy the AML bytecodes + from. + @param [in, out] Context Contains a forward Stream to write to. + (AML_STREAM*)Context. + @param [in, out] Status At entry, contains the status returned by the + last call to this exact function during the + enumeration. + As exit, contains the returned status of the + call to this function. + Optional, can be NULL. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +STATIC +BOOLEAN +EFIAPI +AmlSerializeNodeCallback ( + IN AML_NODE_HEADER * Node, + IN OUT VOID * Context, OPTIONAL + IN OUT EFI_STATUS * Status OPTIONAL + ) +{ + EFI_STATUS Status1; + + CONST AML_DATA_NODE * DataNode; + CONST AML_OBJECT_NODE * ObjectNode; + AML_STREAM * FStream; + + // Bytes needed to store OpCode[1] + SubOpcode[1] + MaxPkgLen[4] =3D 6 b= ytes. + UINT8 ObjectNodeInfoArray[6]; + UINT32 Index; + BOOLEAN ContinueEnum; + + CONST AML_OBJECT_NODE * ParentNode; + EAML_PARSE_INDEX IndexPtr; + + if (!IS_AML_NODE_VALID (Node) || + (Context =3D=3D NULL)) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto error_handler; + } + + // Ignore the second fixed argument of method invocation nodes + // as the information stored there (the argument count) is not in the + // ACPI specification. + ParentNode =3D (CONST AML_OBJECT_NODE*)AmlGetParent ((AML_NODE_HEADER*)N= ode); + if (IS_AML_OBJECT_NODE (ParentNode) && + AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0) && + AmlIsNodeFixedArgument (Node, &IndexPtr)) { + if (IndexPtr =3D=3D EAmlParseIndexTerm1) { + if (Status !=3D NULL) { + *Status =3D EFI_SUCCESS; + } + return TRUE; + } + } + + Status1 =3D EFI_SUCCESS; + ContinueEnum =3D TRUE; + FStream =3D (AML_STREAM*)Context; + + if (IS_AML_DATA_NODE (Node)) { + // Copy the content of the Buffer for a DataNode. + DataNode =3D (AML_DATA_NODE*)Node; + Status1 =3D AmlStreamWrite ( + FStream, + DataNode->Buffer, + DataNode->Size + ); + if (EFI_ERROR (Status1)) { + ASSERT (0); + ContinueEnum =3D FALSE; + goto error_handler; + } + + } else if (IS_AML_OBJECT_NODE (Node) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IS_PSEUDO_OPCODE)) { + // Ignore pseudo-opcodes as they are not part of the + // ACPI specification. + + ObjectNode =3D (AML_OBJECT_NODE*)Node; + + Index =3D 0; + // Copy the opcode(s). + ObjectNodeInfoArray[Index++] =3D ObjectNode->AmlByteEncoding->OpCode; + if (ObjectNode->AmlByteEncoding->OpCode =3D=3D AML_EXT_OP) { + ObjectNodeInfoArray[Index++] =3D ObjectNode->AmlByteEncoding->SubOpC= ode; + } + + // Copy the PkgLen. + if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) { + Index +=3D AmlSetPkgLength ( + ObjectNode->PkgLen, + &ObjectNodeInfoArray[Index] + ); + } + + Status1 =3D AmlStreamWrite ( + FStream, + ObjectNodeInfoArray, + Index + ); + if (EFI_ERROR (Status1)) { + ASSERT (0); + ContinueEnum =3D FALSE; + goto error_handler; + } + } // IS_AML_OBJECT_NODE (Node) + +error_handler: + if (Status !=3D NULL) { + *Status =3D Status1; + } + return ContinueEnum; +} + +/** Serialize a tree to create an ACPI DSDT/SSDT table. + + If: + - the content of BufferSize is >=3D to the size needed to serialize the + definition block; + - Buffer is not NULL; + first serialize the ACPI DSDT/SSDT header from the root node, + then serialize the AML blob from the rest of the tree. + + The content of BufferSize is always updated to the size needed to + serialize the definition block. + + @param [in] RootNode Pointer to a root node. + @param [in] Buffer Buffer to write the DSDT/SSDT table to. + If Buffer is NULL, the size needed to + serialize the DSDT/SSDT table is returned + in BufferSize. + @param [in, out] BufferSize Pointer holding the size of the Buffer. + Its content is always updated to the size + needed to serialize the DSDT/SSDT table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlSerializeTree ( + IN AML_ROOT_NODE * RootNode, + IN UINT8 * Buffer, OPTIONAL + IN OUT UINT32 * BufferSize + ) +{ + EFI_STATUS Status; + AML_STREAM FStream; + UINT32 TableSize; + + if (!IS_AML_ROOT_NODE (RootNode) || + (BufferSize =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Compute the total size of the AML blob. + Status =3D AmlComputeSize ( + (CONST AML_NODE_HEADER*)RootNode, + &TableSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the size of the ACPI header. + TableSize +=3D (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER); + + // Check the size against the SDT header. + // The Length field in the SDT Header is updated if the tree has + // been modified. + if (TableSize !=3D RootNode->SdtHeader->Length) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Buffer is not big enough, or NULL. + if ((TableSize < *BufferSize) || (Buffer =3D=3D NULL)) { + *BufferSize =3D TableSize; + return EFI_SUCCESS; + } + + // Initialize the stream to the TableSize that is needed. + Status =3D AmlStreamInit ( + &FStream, + Buffer, + TableSize, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Serialize the header. + Status =3D AmlStreamWrite ( + &FStream, + (UINT8*)RootNode->SdtHeader, + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D EFI_SUCCESS; + AmlEnumTree ( + (AML_NODE_HEADER*)RootNode, + AmlSerializeNodeCallback, + (VOID*)&FStream, + &Status + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Update the checksum. + return AcpiPlatformChecksum ((EFI_ACPI_DESCRIPTION_HEADER*)Buffer); +} + +/** Serialize an AML definition block. + + This functions allocates memory with the "AllocateZeroPool ()" + function. This memory is used to serialize the AML tree and is + returned in the Table. + + @param [in] RootNode Root node of the tree. + @param [out] Table On return, hold the serialized + definition block. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlSerializeDefinitionBlock ( + IN AML_ROOT_NODE * RootNode, + OUT EFI_ACPI_DESCRIPTION_HEADER ** Table + ) +{ + EFI_STATUS Status; + UINT8 * TableBuffer; + UINT32 TableSize; + + if (!IS_AML_ROOT_NODE (RootNode) || + (Table =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *Table =3D NULL; + TableBuffer =3D NULL; + TableSize =3D 0; + + // Get the size of the SSDT table. + Status =3D AmlSerializeTree ( + RootNode, + TableBuffer, + &TableSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + TableBuffer =3D (UINT8*)AllocateZeroPool (TableSize); + if (TableBuffer =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to allocate memory for Table Buffer." + )); + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Serialize the tree to a SSDT table. + Status =3D AmlSerializeTree ( + RootNode, + TableBuffer, + &TableSize + ); + if (EFI_ERROR (Status)) { + FreePool (TableBuffer); + ASSERT (0); + } else { + // Save the allocated Table buffer in the table list + *Table =3D (EFI_ACPI_DESCRIPTION_HEADER*)TableBuffer; + } + + return Status; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64090): https://edk2.groups.io/g/devel/message/64090 Mute This Topic: https://groups.io/mt/76149159/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64092+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245826651803.4077695121942; Wed, 12 Aug 2020 08:23:46 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Ev2qYY1788612xca81YaFD7R; Wed, 12 Aug 2020 08:23:45 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.48]) by mx.groups.io with SMTP id smtpd.web12.16977.1597245817349588238 for ; Wed, 12 Aug 2020 08:23:37 -0700 X-Received: from DB6PR0202CA0012.eurprd02.prod.outlook.com (2603:10a6:4:29::22) by PR3PR08MB5787.eurprd08.prod.outlook.com (2603:10a6:102:90::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.15; Wed, 12 Aug 2020 15:23:34 +0000 X-Received: from DB5EUR03FT048.eop-EUR03.prod.protection.outlook.com (2603:10a6:4:29:cafe::df) by DB6PR0202CA0012.outlook.office365.com (2603:10a6:4:29::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:34 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64092+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB5EUR03FT048.mail.protection.outlook.com (10.152.21.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:34 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:34 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 95ec4a0c4bf8f715 X-CR-MTA-TID: 64aa7808 X-Received: from e406bd03f346.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id EB05D293-B403-4B74-BFBA-45EDBD767A24.1; Wed, 12 Aug 2020 15:23:28 +0000 X-Received: from EUR01-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id e406bd03f346.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:28 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kvf2bWyIjMuIf0ctrCFAil1w6TYUxSuc4WbOQeesu0f1U6pYEzroLWx4qYHD+Yw/1Et1xpcoMJuhbYMeFSPjnUDsmE+LMxdU2Y3xWZBRpi5vbPo9XyKUZjQwIX12Dz/Bu+FmuDbzKahqYG3cD0tDpCz0c1CRAFTabP6DpHJWP4AIze4WhLkhMou82sjnacsq8T4WBO0CVtsCCbxLxx6y1MH/TDlDbsUQNtcVG0+y8cWxMCoVE6TBReDvai5fJhHWhzFIKHXB5WgrgvymQEBT1baUBPjJqq4dU1g/svz7icLMfIqaGWmFyuHPqK+Fd2SyxPujmKSagyzWuuXsdJETEQ== 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-SenderADCheck; bh=DpXpBZvpFmWiljNFnAJrKkB1C8sZYIa1Cls6IKw/gqM=; b=bKvnrLfP66ZkDA5nvJee1W+36pjCkG88giIklwHXyeX/YEs8RFNoBC79/fXloo7LJg9qzD7kk4ZcJFdM++gPuLlTL23Vv1cIblsi+JhkH4uOUGJnKboULOmDMQqeO47rV2VWD1pZwrwbwgQvNPFy1jcyazfffW5Xvh+6kXXW/at841aOpTiPfTriwZzKM4zk4M98BH2jDTg5+39INqghfecvHfal0rvg+OSva2+3kExvAAK9d4Of0BoPgboTVp1HnP8NaqcAxLRFJjQU0sXQ1XKOZw+NUB0MrnybSlWq+wC8hqlywgB2cEbh/e2TSmohGiJQDcr+tFX4praoJpkGsA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR0402CA0022.eurprd04.prod.outlook.com (2603:10a6:4:91::32) by AM6PR08MB3381.eurprd08.prod.outlook.com (2603:10a6:20b:43::26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:26 +0000 X-Received: from DB5EUR03FT054.eop-EUR03.prod.protection.outlook.com (2603:10a6:4:91:cafe::87) by DB6PR0402CA0022.outlook.office365.com (2603:10a6:4:91::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:26 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT054.mail.protection.outlook.com (10.152.20.248) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:26 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:24 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:23 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 14/30] DynamicTablesPkg: AML debug logging Date: Wed, 12 Aug 2020 16:22:20 +0100 Message-ID: <20200812152236.31164-15-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4a4162f3-c647-4606-5960-08d83ed3ad61 X-MS-TrafficTypeDiagnostic: AM6PR08MB3381:|PR3PR08MB5787: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2958;OLM:2958; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: nUXpgxh0koqwWRDd9YwWrbrogln+CmwkyiLjP1GfC39/PsGCeVR5NFZO6nO3lKVnIA7IN6XQwCibSZ2iUvQaPPGOG/3lqK7K5rmqPAgyIIgYdcoDZ0o8jl+yn1oIAQ7NZLzOKwiIC0ZGwnkVePFrvVfexgjaa1NqehoxPQNT8cGfxyEyLlvKGP57JRhJLEKap7fL2CBt9jnomWVSo2StdTSJWu2UpcsCHXbZVuQczzlchBYqHItij02ld+FIAbsPfjkVjf1eg4W5gOHbxHjlLLsQMB6gM/G6mioH/V70fQ+ZBo+VwBOECkwm2Ihan9XlyFwB1CIbNZzSbiJ25v9OfoXn0jVklakY6ff0kBsbTaobt2+TxCiF+hcEW18yzTgf7tO4vQL8EgHG6/oGbdOyDQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(396003)(376002)(346002)(39860400002)(136003)(46966005)(6916009)(26005)(336012)(356005)(82310400002)(47076004)(82740400003)(81166007)(186003)(54906003)(316002)(478600001)(36756003)(83380400001)(7696005)(2616005)(8936002)(44832011)(5660300002)(1076003)(30864003)(426003)(86362001)(70206006)(2906002)(70586007)(4326008)(8676002);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3381 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT048.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: e8a593e3-d455-490e-ebeb-08d83ed3a8ea X-Microsoft-Antispam-Message-Info: xhMxJEoHme7ROSuQSIHy4i/jRFxalwNejJDZoojYJ7mL2ZLovXp8/XmrP/PDQ82AJbEsqxYVzHUMwfJnk/+6gGdoUF0GpErJCUbagy7QYqkBme/l/rOhF6WT0oj+WmzAcLbppThsgGZRgh9Tlu3/1dTs1+5+IvONXs6NfJL5DYYNTgcBNVKExrRRpH9qHs0TQyFWqbHc6grEvKY9WmZwKzaal1aGvb47Eo/fAqixO7EX3uFEi4PACeTFITY//RPmc1ezVDX0E/b8rfmcbFR6A43Urjyg4VIXXG3IMsrMyJTeP1EbVQwlnG/ds8KWw5FxGrrVOWl/V8rKVnGrV406ZZSWAiyWgaE567kK8465K2NGqzjfExhs1tS0QpglLFWJWzGotKbotNyCw+J0Lznh+A== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:34.0705 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4a4162f3-c647-4606-5960-08d83ed3ad61 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: DB5EUR03FT048.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR3PR08MB5787 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: vcOgC52Su6Ad4UdJSt4Mul4kx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245825; bh=Y9IZ+4lmGZshUiurDHtpx5gWMpD9/BinnSRx6gpMNew=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=jbm8twKP9cMbm2Y0zSC9wuxcJRHSUWm8iy0Tl/o9wvhVotC5OVdT3sGkyt+qf2aQ3ID h7GBGnX7v4t20xzRgCiqTJEg7Zg4loTDEk7hF+Qj6z1QVKjIH6EGiUmHuki9Z/Vd+dNA/ r8hgqUMfgDwlyQdS/6tO/ADw4Cnkwn7q68A= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML debug print functions enable logging of the operations on the AML tree and the data output. The debug logging functionality is enabled for debug builds when the DEBUG_INFO or DEBUG_VERBOSE mask is enabled in the PCD gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c | 546 +++= +++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h | 154 +++= +++ 2 files changed, 700 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint= .c b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c new file mode 100644 index 0000000000000000000000000000000000000000..7b11cc8e994903b3a9d2dcfd124= 1b8a447759717 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c @@ -0,0 +1,546 @@ +/** @file + AML Print Function. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include + +#include +#include +#include +#include + +#if !defined (MDEPKG_NDEBUG) + +/** String table representing AML Data types as defined by EAML_NODE_DATA_= TYPE. +*/ +CONST CHAR8 * NodeDataTypeStrTbl[] =3D { + "EAmlNodeDataTypeNone", + "EAmlNodeDataTypeReserved1", + "EAmlNodeDataTypeReserved2", + "EAmlNodeDataTypeReserved3", + "EAmlNodeDataTypeReserved4", + "EAmlNodeDataTypeReserved5", + "EAmlNodeDataTypeNameString", + "EAmlNodeDataTypeString", + "EAmlNodeDataTypeUInt", + "EAmlNodeDataTypeRaw", + "EAmlNodeDataTypeResourceData", + "EAmlNodeDataTypeFieldPkgLen", + "EAmlNodeDataTypeMax" +}; + +/** String table representing AML Node types as defined by EAML_NODE_TYPE. +*/ +CONST CHAR8 * NodeTypeStrTbl[] =3D { + "EAmlNodeUnknown", + "EAmlNodeRoot", + "EAmlNodeObject", + "EAmlNodeData", + "EAmlNodeMax" +}; + +/** Print Size chars at Buffer address. + + @param [in] ErrorLevel Error level for the DEBUG macro. + @param [in] Buffer Buffer containing the chars. + @param [in] Size Number of chars to print. +**/ +VOID +EFIAPI +AmlDbgPrintChars ( + IN UINT32 ErrorLevel, + IN CONST CHAR8 * Buffer, + IN UINT32 Size + ) +{ + UINT32 i; + + if (Buffer =3D=3D NULL) { + ASSERT (0); + return; + } + + for (i =3D 0; i < Size; i++) { + DEBUG ((ErrorLevel, "%c", Buffer[i])); + } +} + +/** Print an AML NameSeg. + Don't print trailing underscores ('_'). + + @param [in] Buffer Buffer containing an AML NameSeg. +**/ +VOID +EFIAPI +AmlDbgPrintNameSeg ( + IN CONST CHAR8 * Buffer + ) +{ + if (Buffer =3D=3D NULL) { + ASSERT (0); + return; + } + + DEBUG ((DEBUG_INFO, "%c", Buffer[0])); + if ((Buffer[1] =3D=3D AML_NAME_CHAR__) && + (Buffer[2] =3D=3D AML_NAME_CHAR__) && + (Buffer[3] =3D=3D AML_NAME_CHAR__)) { + return; + } + DEBUG ((DEBUG_INFO, "%c", Buffer[1])); + if ((Buffer[2] =3D=3D AML_NAME_CHAR__) && + (Buffer[3] =3D=3D AML_NAME_CHAR__)) { + return; + } + DEBUG ((DEBUG_INFO, "%c", Buffer[2])); + if (Buffer[3] =3D=3D AML_NAME_CHAR__) { + return; + } + DEBUG ((DEBUG_INFO, "%c", Buffer[3])); + return; +} + +/** Print an AML NameString. + + @param [in] Buffer Buffer containing an AML NameString. + @param [in] NewLine Print a newline char at the end of the NameString. +**/ +VOID +EFIAPI +AmlDbgPrintNameString ( + IN CONST CHAR8 * Buffer, + IN BOOLEAN NewLine + ) +{ + UINT8 SegCount; + UINT8 Index; + + if (Buffer =3D=3D NULL) { + ASSERT (0); + return; + } + + // Handle Root and Parent(s). + if (*Buffer =3D=3D AML_ROOT_CHAR) { + Buffer++; + DEBUG ((DEBUG_INFO, "\\")); + } else if (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR) { + do { + Buffer++; + DEBUG ((DEBUG_INFO, "^")); + } while (*Buffer =3D=3D AML_PARENT_PREFIX_CHAR); + } + + // Handle SegCount(s). + if (*Buffer =3D=3D AML_DUAL_NAME_PREFIX) { + Buffer++; + SegCount =3D 2; + } else if (*Buffer =3D=3D AML_MULTI_NAME_PREFIX) { + Buffer++; + // For multi name prefix the seg count is in the second byte. + SegCount =3D *Buffer; + Buffer++; + } else if (AmlIsLeadNameChar (*Buffer)) { + // Only check the first char first to avoid overflow. + // Then the whole NameSeg can be checked. + if (!AmlIsNameSeg (Buffer)) { + ASSERT (0); + return; + } + SegCount =3D 1; + } else if (*Buffer =3D=3D AML_ZERO_OP) { + SegCount =3D 0; + } else { + // Should not be possible. + ASSERT (0); + return; + } + + if (SegCount !=3D 0) { + AmlDbgPrintNameSeg (Buffer); + Buffer +=3D AML_NAME_SEG_SIZE; + for (Index =3D 0; Index < SegCount - 1; Index++) { + DEBUG ((DEBUG_INFO, ".")); + AmlDbgPrintNameSeg (Buffer); + Buffer +=3D AML_NAME_SEG_SIZE; + } + } + + if (NewLine) { + DEBUG ((DEBUG_INFO, "\n")); + } + + return; +} + +/** Print the information contained in the header of the Node. + + @param [in] Node Pointer to a node. + @param [in] Level Level of the indentation. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintNodeHeader ( + IN AML_NODE_HEADER * Node, + IN UINT8 Level + ) +{ + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return; + } + + DEBUG (( + DEBUG_INFO, + "%3d | %-15s | ", + Level, + NodeTypeStrTbl[Node->NodeType] + )); +} + +/** Print fields of a data node. + + @param [in] DataNode Pointer to a data node. + @param [in] Level Level of the indentation. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintDataNode ( + IN AML_DATA_NODE * DataNode, + IN UINT8 Level + ) +{ + UINT32 Idx; + + if (!IS_AML_DATA_NODE (DataNode)) { + ASSERT (0); + return; + } + + AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)DataNode, Level); + + DEBUG ((DEBUG_INFO, "%-36s | ", NodeDataTypeStrTbl[DataNode->DataType])); + DEBUG ((DEBUG_INFO, "0x%04x | ", DataNode->Size)); + + if ((DataNode->DataType =3D=3D EAmlNodeDataTypeNameString) || + (DataNode->DataType =3D=3D EAmlNodeDataTypeString)) { + AmlDbgPrintChars ( + DEBUG_INFO, + (CONST CHAR8*)DataNode->Buffer, + DataNode->Size + ); + } else if (DataNode->DataType =3D=3D EAmlNodeDataTypeUInt) { + switch (DataNode->Size) { + case 1: + { + DEBUG ((DEBUG_INFO, "0x%0x", *((UINT8*)DataNode->Buffer))); + break; + } + case 2: + { + DEBUG ((DEBUG_INFO, "0x%0x", *((UINT16*)DataNode->Buffer))); + break; + } + case 4: + { + DEBUG ((DEBUG_INFO, "0x%0lx", *((UINT32*)DataNode->Buffer))); + break; + } + case 8: + { + DEBUG ((DEBUG_INFO, "0x%0llx", *((UINT64*)DataNode->Buffer))); + break; + } + default: + { + ASSERT (0); + return; + } + } + } else { + // No specific format. + for (Idx =3D 0; Idx < DataNode->Size; Idx++) { + DEBUG ((DEBUG_INFO, "%02x ", DataNode->Buffer[Idx])); + } + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +/** Print fields of an object node. + + @param [in] ObjectNode Pointer to an object node. + @param [in] Level Level of the indentation. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintObjectNode ( + IN AML_OBJECT_NODE * ObjectNode, + IN UINT8 Level + ) +{ + if (!IS_AML_OBJECT_NODE (ObjectNode)) { + ASSERT (0); + return; + } + + AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)ObjectNode, Level); + + DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->OpCode)); + DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->SubOpCode)= ); + + // Print a string corresponding to the field object OpCode/SubOpCode. + if (AmlNodeHasAttribute (ObjectNode, AML_IS_FIELD_ELEMENT)) { + DEBUG ((DEBUG_INFO, "%-15s ", AmlGetFieldOpCodeStr ( + ObjectNode->AmlByteEncoding->OpCode, + 0 + ))); + } else { + // Print a string corresponding to the object OpCode/SubOpCode. + DEBUG ((DEBUG_INFO, "%-15s | ", AmlGetOpCodeStr ( + ObjectNode->AmlByteEncoding->OpCode, + ObjectNode->AmlByteEncoding->SubOpCo= de) + )); + } + + DEBUG ((DEBUG_INFO, "%3d | ", ObjectNode->AmlByteEncoding->MaxIndex)); + DEBUG ((DEBUG_INFO, "0x%08x | ", ObjectNode->AmlByteEncoding->Attribute)= ); + DEBUG ((DEBUG_INFO, "0x%04x | ", ObjectNode->PkgLen)); + if (AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) { + AmlDbgPrintNameString ( + AmlNodeGetName ((CONST AML_OBJECT_NODE*)ObjectNode), + FALSE + ); + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +/** Print fields of a root node. + + @param [in] RootNode Pointer to a root node. + @param [in] Level Level of the indentation. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintRootNode ( + IN AML_ROOT_NODE * RootNode, + IN UINT8 Level + ) +{ + if (!IS_AML_ROOT_NODE (RootNode)) { + ASSERT (0); + return; + } + + AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)RootNode, Level); + + DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->Signature)); + DEBUG ((DEBUG_INFO, "0x%08x | ", RootNode->SdtHeader->Length)); + DEBUG ((DEBUG_INFO, "%3d | ", RootNode->SdtHeader->Revision)); + DEBUG ((DEBUG_INFO, "0x%02x | ", RootNode->SdtHeader->Checksum)); + DEBUG (( + DEBUG_INFO, + "%c%c%c%c%c%c | ", + RootNode->SdtHeader->OemId[0], + RootNode->SdtHeader->OemId[1], + RootNode->SdtHeader->OemId[2], + RootNode->SdtHeader->OemId[3], + RootNode->SdtHeader->OemId[4], + RootNode->SdtHeader->OemId[5] + )); + DEBUG ((DEBUG_INFO, "%-16llx | ", RootNode->SdtHeader->OemTableId)); + DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->OemRevision)); + DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->CreatorId)); + DEBUG ((DEBUG_INFO, "%8x", RootNode->SdtHeader->CreatorRevision)); + DEBUG ((DEBUG_INFO, "\n")); +} + +/** Print a header to help interpreting node information. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintTableHeader ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "Lvl | Node Type |\n")); + DEBUG (( + DEBUG_INFO, + " | %-15s | Signature| Length | Rev | CSum | OemId | " + "OemTableId | OemRev | CreatorId| CreatorRev\n", + NodeTypeStrTbl[EAmlNodeRoot] + )); + DEBUG (( + DEBUG_INFO, + " | %-15s | Op | SubOp| OpName | MaxI| Attribute | " + "PkgLen | NodeName (opt)\n", + NodeTypeStrTbl[EAmlNodeObject] + )); + DEBUG (( + DEBUG_INFO, + " | %-15s | Data Type | Size | " + "Buffer\n", + NodeTypeStrTbl[EAmlNodeData] + )); + DEBUG (( + DEBUG_INFO, + "---------------------------------------" + "---------------------------------------\n" + )); +} + +/** Recursively print the subtree under the Node. + This is an internal function. + + @param [in] Node Pointer to the root of the subtree to prin= t. + Can be a root/object/data node. + @param [in] Recurse If TRUE, recurse. + @param [in] Level Level in the tree. +**/ +STATIC +VOID +EFIAPI +AmlDbgPrintTreeInternal ( + IN AML_NODE_HEADER * Node, + IN BOOLEAN Recurse, + IN UINT8 Level + ) +{ + AML_NODE_HEADER * ChildNode; + + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return; + } + + if (IS_AML_DATA_NODE (Node)) { + AmlDbgPrintDataNode ((AML_DATA_NODE*)Node, Level); + return; + } else if (IS_AML_OBJECT_NODE (Node)) { + AmlDbgPrintObjectNode ((AML_OBJECT_NODE*)Node, Level); + } else if (IS_AML_ROOT_NODE (Node)) { + AmlDbgPrintRootNode ((AML_ROOT_NODE*)Node, Level); + } else { + // Should not be possible. + ASSERT (0); + return; + } + + if (!Recurse) { + return; + } + + // Get the first child node. + ChildNode =3D AmlGetNextSibling (Node, NULL); + while (ChildNode !=3D NULL) { + ASSERT (Level < MAX_UINT8); + AmlDbgPrintTreeInternal (ChildNode, Recurse, (UINT8)(Level + 1)); + ChildNode =3D AmlGetNextSibling (Node, ChildNode); + } +} + +/** Print Node information. + + @param [in] Node Pointer to the Node to print. + Can be a root/object/data node. +**/ +VOID +EFIAPI +AmlDbgPrintNode ( + IN AML_NODE_HEADER * Node + ) +{ + AmlDbgPrintTableHeader (); + AmlDbgPrintTreeInternal (Node, FALSE, 0); +} + +/** Recursively print the subtree under the Node. + + @param [in] Node Pointer to the root of the subtree to print. + Can be a root/object/data node. +**/ +VOID +EFIAPI +AmlDbgPrintTree ( + IN AML_NODE_HEADER * Node + ) +{ + AmlDbgPrintTableHeader (); + AmlDbgPrintTreeInternal (Node, TRUE, 0); +} + +/** This function performs a raw data dump of the ACPI table. + + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. +**/ +VOID +EFIAPI +DumpRaw ( + IN CONST UINT8 * Ptr, + IN UINT32 Length + ) +{ + UINT32 ByteCount; + UINT32 PartLineChars; + UINT32 AsciiBufferIndex; + CHAR8 AsciiBuffer[17]; + + ByteCount =3D 0; + AsciiBufferIndex =3D 0; + + DEBUG ((DEBUG_VERBOSE, "Address : 0x%p\n", Ptr)); + DEBUG ((DEBUG_VERBOSE, "Length : %lld", Length)); + + while (ByteCount < Length) { + if ((ByteCount & 0x0F) =3D=3D 0) { + AsciiBuffer[AsciiBufferIndex] =3D '\0'; + DEBUG ((DEBUG_VERBOSE, " %a\n%08X : ", AsciiBuffer, ByteCount)); + AsciiBufferIndex =3D 0; + } else if ((ByteCount & 0x07) =3D=3D 0) { + DEBUG ((DEBUG_VERBOSE, "- ")); + } + + if ((*Ptr >=3D ' ') && (*Ptr < 0x7F)) { + AsciiBuffer[AsciiBufferIndex++] =3D *Ptr; + } else { + AsciiBuffer[AsciiBufferIndex++] =3D '.'; + } + + DEBUG ((DEBUG_VERBOSE, "%02X ", *Ptr++)); + + ByteCount++; + } + + // Justify the final line using spaces before printing + // the ASCII data. + PartLineChars =3D (Length & 0x0F); + if (PartLineChars !=3D 0) { + PartLineChars =3D 48 - (PartLineChars * 3); + if ((Length & 0x0F) <=3D 8) { + PartLineChars +=3D 2; + } + while (PartLineChars > 0) { + DEBUG ((DEBUG_VERBOSE, " ")); + PartLineChars--; + } + } + + // Print ASCII data for the final line. + AsciiBuffer[AsciiBufferIndex] =3D '\0'; + DEBUG ((DEBUG_VERBOSE, " %a\n\n", AsciiBuffer)); +} + +#endif // MDEPKG_NDEBUG diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint= .h b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h new file mode 100644 index 0000000000000000000000000000000000000000..68f4c7416948a20484b6d5448c2= 31add3f1186dd --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h @@ -0,0 +1,154 @@ +/** @file + AML Debug Print. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_PRINT_H_ +#define AML_PRINT_H_ + +/* This header file does not include internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions + must be included by the caller file. The function prototypes must + only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node + definitions. + This allows to keep the functions defined here both internal and + potentially external. If necessary, any function of this file can + be exposed externally. + The Api folder is internal to the AmlLib, but should only use these + functions. They provide a "safe" way to interact with the AmlLib. +*/ + +#if !defined (MDEPKG_NDEBUG) + +#include + +/** + @defgroup DbgPrintApis Print APIs for debugging. + @ingroup AMLLib + @{ + Print APIs provide a way to print: + - A buffer; + - A (root/object/data) node; + - An AML tree/branch; + - The AML NameSpace from the root node. + @} +*/ + +/** This function performs a raw data dump of the ACPI table. + + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. +**/ +VOID +EFIAPI +DumpRaw ( + IN CONST UINT8 * Ptr, + IN UINT32 Length + ); + +/** Print Size chars at Buffer address. + + @ingroup DbgPrintApis + + @param [in] ErrorLevel Error level for the DEBUG macro. + @param [in] Buffer Buffer containing the chars. + @param [in] Size Number of chars to print. +**/ +VOID +EFIAPI +AmlDbgPrintChars ( + IN UINT32 ErrorLevel, + IN CONST CHAR8 * Buffer, + IN UINT32 Size + ); + +/** Print an AML NameSeg. + Don't print trailing underscores ('_'). + + @param [in] Buffer Buffer containing an AML NameSeg. +**/ +VOID +EFIAPI +AmlDbgPrintNameSeg ( + IN CONST CHAR8 * Buffer + ); + +/** Print an AML NameString. + + @param [in] Buffer Buffer containing an AML NameString. + @param [in] NewLine Print a newline char at the end of the NameString. +**/ +VOID +EFIAPI +AmlDbgPrintNameString ( + IN CONST CHAR8 * Buffer, + IN BOOLEAN NewLine + ); + +/** Print Node information. + + @ingroup DbgPrintApis + + @param [in] Node Pointer to the Node to print. + Can be a root/object/data node. +**/ +VOID +EFIAPI +AmlDbgPrintNode ( + IN AML_NODE_HANDLE Node + ); + +/** Recursively print the subtree under the Node. + + @ingroup DbgPrintApis + + @param [in] Node Pointer to the root of the subtree to print. + Can be a root/object/data node. +**/ +VOID +EFIAPI +AmlDbgPrintTree ( + IN AML_NODE_HANDLE Node + ); + +/** Print the absolute pathnames in the AML namespace of + all the nodes in the tree starting from the Root node. + + @ingroup DbgPrintApis + + @param [in] RootNode Pointer to a root node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlDbgPrintNameSpace ( + IN AML_ROOT_NODE_HANDLE RootNode + ); + +#else + +#define DumpRaw(Ptr, Length) + +#define AmlDbgPrintChars(ErrorLevel, Buffer, Size) + +#define AmlDbgPrintNameSeg(Buffer) + +#define AmlDbgPrintNameString(Buffer,NewLine) + +#define AmlDbgPrintNode(Node) + +#define AmlDbgPrintTree(Node) + +#define AmlDbgPrintNameSpace(RootNode) + +#endif // MDEPKG_NDEBUG + +#endif // AML_PRINT_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64092): https://edk2.groups.io/g/devel/message/64092 Mute This Topic: https://groups.io/mt/76149164/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64093+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 159724583114733.99670990612731; Wed, 12 Aug 2020 08:23:51 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id KhqYYY1788612xbRzPMq3PTf; Wed, 12 Aug 2020 08:23:50 -0700 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com (EUR05-DB8-obe.outbound.protection.outlook.com [40.107.20.51]) by mx.groups.io with SMTP id smtpd.web12.16979.1597245821256683518 for ; Wed, 12 Aug 2020 08:23:41 -0700 X-Received: from AM5P194CA0003.EURP194.PROD.OUTLOOK.COM (2603:10a6:203:8f::13) by AM8PR08MB5748.eurprd08.prod.outlook.com (2603:10a6:20b:1df::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: from VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:8f:cafe::90) by AM5P194CA0003.outlook.office365.com (2603:10a6:203:8f::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:37 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64093+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT044.mail.protection.outlook.com (10.152.19.106) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:37 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 5bc09c2383faf209 X-CR-MTA-TID: 64aa7808 X-Received: from 56d36f88ac5d.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 9BA7A9EF-79D0-49FD-AB55-95B07466ECA0.1; Wed, 12 Aug 2020 15:23:32 +0000 X-Received: from EUR01-VE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 56d36f88ac5d.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:32 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=V5tmrxn87YesSwnJg/l7iowPxXjYGEmMssz+OLadRN58E5Wk8LrVssM4FtAh/3JTtUEWry+pztkvOkyeoqbfMdN1Lcpua1jYPvIwj+Q1UDBkar9WzY2qy+TTOJNzioFMFjanKu+yd+XozVmdlkAynkEO2RRlcDNwQmWCCN/HoSYvEfcj/IYxRwpZ/AMktom8012EquH6IUhYM46Ttl0W6pvLHToOG/u0ZAw/vqXtt1OzX+YVis6/oyHuJaTskDBjOUiyzASW6QQyVYhMqccxiRaqwBloC/3mYqBsQ4ZuD8f3sqoy7xvmlBoylKG75rYo2vx8vBHBb4JVqHKPf9/Hrg== 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-SenderADCheck; bh=LK+FQxlF8SePvcHimhyC25DW/7lhe13RrbSV2YZ0lZc=; b=hkiLp2QlSK+Xehcw4L0XI2xnTL4QwD0a57MGwuyAmIVVhYY5ybRlsBys+1qOPpXvZAewcgrEnkXDkzvfO66NGmJIxj+bl9vq6/BQ7cmmf7cT2IkOGKoFS9ZLv2TQN2Hio4zPftSQDxXb5E4kh6L0AN8SiVZ+NfUnHQnNM1vEpZXvF+m9aB4DqgUj26t4wAUPMDhyCdqnjEVGaUi10fY7aD0LrUa/qHfcfFIqUATt/OEFttlAB8zn8ycmZfvFPCKucQgZHTciKiqC+H3JK/OPNEa7AtRK1BXTzou3qivlvPKDXy5vaXe4rmHeOynDXJ33D0HsBrA7qQKNDdJw6/zFpg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6P193CA0111.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::16) by VI1PR08MB4175.eurprd08.prod.outlook.com (2603:10a6:803:ea::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:28 +0000 X-Received: from AM5EUR03FT050.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:85:cafe::d7) by AM6P193CA0111.outlook.office365.com (2603:10a6:209:85::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:28 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT050.mail.protection.outlook.com (10.152.17.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:28 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:27 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:25 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:24 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 15/30] DynamicTablesPkg: AML ACPI Namespace interface Date: Wed, 12 Aug 2020 16:22:21 +0100 Message-ID: <20200812152236.31164-16-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: db0fbb74-8af3-44d1-2db7-08d83ed3af93 X-MS-TrafficTypeDiagnostic: VI1PR08MB4175:|AM8PR08MB5748: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:10000;OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: K3f4PUQ/FCMti90Q6P4lSr1N+qmSFBPICw4qMOMRwTYFkAyeZlrecxNZGYQ2DgFbtKXh1ZeoOq8zmQFtXbpjndetrbUwHnrtOqdwb3URsyPYiBRck1VUPuQNJJCLhib14H8RUp42MW7J99VaEiR7f0C2J28uDKBrxTQYXvUWTKF9TczhqYxHcbj27YbtA+Gz5GvZofyi6frInwTafraS6eWIJcZu7CUaxriIsNJfwIpZX8XZKdhGeUiohxTcCGannQPnpW+yXJkWIFJvuTTLmpLUWIpkYvjpqXGpGEDEEsQ4xsh/qSmwvSYHWv7HrvrzJGOtBdU8uO6nX310Vasv1SZcV/wCoqkLI4gBORdqba86cw93+w1T43g6mbqNTPdr4MO8CLVb4Uv9GpyU4M8b7A== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(376002)(346002)(136003)(39860400002)(396003)(46966005)(478600001)(83380400001)(356005)(82310400002)(1076003)(4326008)(70206006)(81166007)(86362001)(2906002)(5660300002)(70586007)(6666004)(30864003)(426003)(316002)(44832011)(8676002)(8936002)(2616005)(26005)(82740400003)(7696005)(54906003)(336012)(186003)(6916009)(36756003)(47076004)(559001)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB4175 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: b6d2f6e8-d437-4f26-ec55-08d83ed3aa29 X-Microsoft-Antispam-Message-Info: l4Ye6nhq/+XTjoE8980I/CdaIzM33nDIRfI1l4rhCUFBg0JDrm2AyeFUgekQwxVsTBv9A1YTIFgPHaxhdMSSoHaSn/hfLW81ME/EvnEAZb+adtem5dzlSqCemteRdhKOtlE67dFgvaxlO+vratMJx96j289lhP/JBqoa6S6yxWsBbWpQ3Yh04dkoem+jqsF5GB3vD4CmyhE8nNuowBvc26KIMq8lz5rAFX6HVgSF5It0rlmSnv++GMXd9Gj3t36zh2gS/yyC324fLoFGzsvGel+icj7J8XkmcjvJ3ss4X76j+UWSPG8m/DSXTAC+adn5lZja8n2Nsd7sH0lBnxowMfEpgNjS5cGHvEnHq6rU23JuUfQTEN/xJbx90YY4Nk+181temCmArLpQXzO1EHZEvw== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:37.6147 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: db0fbb74-8af3-44d1-2db7-08d83ed3af93 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: VE1EUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR08MB5748 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: zxHKuIhYjbkvszTjA7AmbbDQx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245830; bh=ONEFimvQSbrGfkzrQ2dpplv55JIn8aCVo+rXAUMM06k=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=mc6abs1DG/CvDZOiAm5PGKv0ztDuuCLheLIwHTa5ZNkQU8PcocbkKaV/7M/aiVMlbah gJlyTdvyBE9pSuJpT5joRMz0mSB0wKdkjG1zilP1CjfdtdpjWy2+vs6pDQ3uZP+qIecoT C7HHaNmFT8irWlsMXswhhnGj7QyrE8vhzDg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML is a declarative language that is processed by the ACPI AML interpreter. The ACPI AML interpreter will compile the set of declarations into the ACPI Namespace at definition block load time. The hardware information described in AML is effectively mapped in the ACPI Namespace. The AML ACPI namespace interface implement the functionality to search the ACPI Namespace. Example: The AmlFindNode() can be used to locate a device node in the ACPI namespace using an ASL path as the search input. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c | 1501 +++= +++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h | 74 + 2 files changed, 1575 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.= c b/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c new file mode 100644 index 0000000000000000000000000000000000000000..dc373748903dd55fa4492874329= f2b433c698c02 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c @@ -0,0 +1,1501 @@ +/** @file + AML NameSpace. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +/* Lexicon: + + NameSeg: + - An ASL NameSeg is a name made of at most 4 chars. + Cf. ACPI 6.3 specification, s19.2.2 'Name and Pathname Terms'. + - An AML NameSeg is a name made of 4 chars. + Cf. ACPI 6.3 specification, s20.2.2 'Name Objects Encoding'. + + NameString: + A NameString is analogous to a pathname. It is made of 0 to 255 NameSegs. + A NameString can be prefixed by a root char ('\') or 0 to 255 carets ('^= '). + + A NameString can be ASL or AML encoded. + AML NameStrings can have a NameString prefix (dual or multi-name prefix) + between the root/carets and the list of NameSegs. If the prefix is the + multi-name prefix, then the number of NameSegs is encoded on one single = byte. + Cf. ACPI 6.3 specification, s19.2.2 'Name and Pathname Terms'. + Cf. ACPI 6.3 specification, s20.2.2 'Name Objects Encoding'. + + Namespace level: + One level in the AML Namespace level corresponds to one NameSeg. In ASL, + objects names are NameStrings. This means a device can have a name which + spans multiple levels. + E.g.: The ASL code: Device (CLU0.CPU0) corresponds to 2 levels. + + Namespace node: + A namespace node is an object node which has an associated name, and whi= ch + changes the current scope. + E.g.: + 1. The "Device ()" ASL statement adds a name to the AML namespace and + changes the current scope to the device scope, this is a namespace = node. + 2. The "Scope ()" ASL statement changes the current scope, this is a + namespace node. + 3. A method invocation has a name, but does not add nor change the cur= rent + AML scope. This is not a namespace node. + + - Object nodes with the AML_IN_NAMESPACE attribute are namespace nodes. + Buffers (), Packages (), etc. are not part of the namespace. It is how= ever + possible to associate them with a name with the Name () ASL statement. + - The root node is considered as being part of the namespace. + - Some resource data elements can have a name when defining them in + an ASL statement. However, this name is stripped by the ASL compiler. + Thus, they don't have a name in the AML bytestream, and are therefore + not part of the AML namespace. + - Field list elements are part of the namespace. + Fields created by an CreateXXXField () ASL statement are part of the + namespace. The name of these node can be found in the third or fourth + fixed argument. The exact index of the name can be found in the NameIn= dex + field of the AML_BYTE_ENCODING array. + Field are at the same level as their ASL statement in the namespace. + E.g: + Scope (\) { + OperationRegion (REG0, SystemIO, 0x100, 0x100) + Field (REG0, ByteAcc, NoLock, Preserve) { + FIE0, 1, + FIE1, 5 + } + + Name (BUF0, Buffer (100) {}) + CreateField (BUF0, 5, 2, MEM0) + } + + produces this namespace: + \ (Root) + \-REG0 + \-FIE0 + \-FIE1 + \-BUF0 + \-MEM0 + + Raw AML pathname or Raw AML NameString: + In order to easily manipulate AML NameStrings, the non-NameSegs chars are + removed in raw pathnames/NameStrings. Non-NameSegs chars are the + root char ('\'), carets ('^') and NameString prefixes (Dual/Multi name c= har). + E.g. The following terminology is defined in this AML Library. + ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0" + AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCC= C" + Raw absolute path: "AAAABBBBCCCC" + + Multi-name: + A NameString with at least 2 NameSegs. A node can have a name which spans + multiple namespace levels. +*/ + +#include + +#include +#include +#include +#include +#include +#include + +/** Context of the path search callback function. + + The function finding a node from a path and a reference node enumerates + the namespace nodes in the tree and compares their absolute path with the + searched path. The enumeration function uses a callback function that can + receive a context. + This structure is used to store the context information required in the + callback function. +*/ +typedef struct AmlPathSearchContext { + /// Backward stream holding the raw AML absolute searched path. + AML_STREAM * SearchPathBStream; + + /// An empty backward stream holding a pre-allocated buffer. This preven= ts + /// from having to do multiple allocations during the search. + /// This stream is used to query the raw AML absolute path of the node + /// currently being probed. + AML_STREAM * CurrNodePathBStream; + + /// If the node being visited is the node being searched, + /// i.e. its path and the searched path match, + /// save its reference in this pointer. + AML_NODE_HEADER * OutNode; +} AML_PATH_SEARCH_CONTEXT; + +/** Return the first AML namespace node up in the parent hierarchy. + + Return the root node if no namespace node is found is the hierarchy. + + @param [in] Node Node to look at the parents from. + If Node is the root node, OutNode is NULL. + @param [out] OutNode If a namespace node is found, pointer to the + first namespace node of Node's parents. + Stop at the root node otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + **/ +EFI_STATUS +EFIAPI +AmlGetFirstAncestorNameSpaceNode ( + IN CONST AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** OutNode + ) +{ + if (!IS_AML_NODE_VALID (Node) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // If Node is the root node, return NULL. + if (IS_AML_ROOT_NODE (Node)) { + *OutNode =3D NULL; + return EFI_SUCCESS; + } else { + // Else, get the parent node. + Node =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + // Continue getting the parent node while no namespace node is encounter= ed. + while (TRUE) { + if (IS_AML_ROOT_NODE (Node)) { + break; + } else if (AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE + )) { + break; + } else { + Node =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (!IS_AML_NODE_VALID (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + } // while + + *OutNode =3D (AML_NODE_HEADER*)Node; + return EFI_SUCCESS; +} + +/** Climb up the AML namespace hierarchy. + + This function get the ancestor namespace node in the AML namespace. + If Levels is not zero, skip Levels namespace nodes in the AML namespace. + If Levels is zero, return the first ancestor namespace node. + I.e. if Levels =3D n, this function returns the (n + 1) ancestor. + + @param [in] Node Pointer to an object node. + @param [in, out] Levels Pointer holding a number of AML namespace leve= ls: + - At entry, the number of levels to go up in + the AML namespace; + - At exit, the number of levels that still ne= ed + to be climbed in case of a multi-named node. + Indeed, if a node with a multi-name is foun= d, + and Levels is less than the number of NameS= egs + in this name, then the function returns with + the number of levels that still need to be + climbed. + E.g.: If the first ancestor node's name is + "AAAA.BBBB.CCCC" and + Levels =3D 2 -> i.e go up 3 levels + \ + ... + \-"AAAA.BBBB.CCCC" <----- OutNode + \-"DDDD" <----- Node (I= nput) + + The function should ideally return a = node + with the name "AAAA". However, it is = not + possible to split the node name + "AAAA.BBBB.CCCC" to "AAAA". + Thus, OutNode is set to the input nod= e, + and Levels =3D 2. + In most cases the number of levels to climb + correspond to non multi-name node, and ther= efore + Levels =3D 0 at exit. + @param [out] HasRoot The returned node in OutNode has an AML absolu= te + name, starting with a root char ('\'), or if O= utNode + is the root node. + @param [out] OutNode The Levels+1 namespace ancestor of the input n= ode in + the AML namespace. Must be the root node or a + namespace node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlGetAncestorNameSpaceNode ( + IN CONST AML_OBJECT_NODE * Node, + IN OUT UINT32 * Levels, + OUT UINT32 * HasRoot, + OUT CONST AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + + CONST AML_NODE_HEADER * NameSpaceNode; + CHAR8 * NodeName; + UINT32 ParentCnt; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if (!IS_AML_OBJECT_NODE (Node) || + (Levels =3D=3D NULL) || + (HasRoot =3D=3D NULL) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentCnt =3D *Levels; + *HasRoot =3D 0; + + // ParentCnt namespace levels need to be climbed. + do { + // Get the next namespace node in the hierarchy. + Status =3D AmlGetFirstAncestorNameSpaceNode ( + (CONST AML_NODE_HEADER*)Node, + (AML_NODE_HEADER**)&NameSpaceNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Node =3D (CONST AML_OBJECT_NODE*)NameSpaceNode; + + if (IS_AML_ROOT_NODE (Node)) { + // Node is the root node. It is not possible to go beyond. + if (ParentCnt !=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + *HasRoot =3D 1; + break; + } + + NodeName =3D AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node); + if (NodeName =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Analyze the node name. + Status =3D AmlParseNameStringInfo ( + NodeName, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + if (Root !=3D 0) { + // NodeName is an absolute pathname. + *HasRoot =3D Root; + + // If the node has Root then it cannot have ParentPrefixes (Carets). + if (ParentPrefix !=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (SegCount =3D=3D ParentCnt) { + // There are exactly enough AML namespace levels to consume. + // This means the root node was the searched node. + Node =3D (CONST AML_OBJECT_NODE*)AmlGetRootNode ( + (CONST AML_NODE_HEADER*)Node + ); + if (!IS_AML_ROOT_NODE (Node)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParentCnt =3D 0; + break; + } else if (ParentCnt < SegCount) { + // There are too many AML namespace levels in this name. + // ParentCnt has the right value, just return. + break; + } else { + // ParentCnt > SegCount + // Return error as there must be at least ParentCnt AML namespace + // levels left in the absolute path. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } else { + // Root is 0. + if (ParentCnt < SegCount) { + // NodeName is a relative path. + // NodeName has enough levels to consume all the ParentCnt. + // Exit. + break; + } else if (SegCount =3D=3D ParentCnt) { + // There are exactly enough AML namespace levels to consume. + if (ParentPrefix =3D=3D 0) { + // The node name doesn't have any carets. Get the next namespace + // node and return. + Status =3D AmlGetFirstAncestorNameSpaceNode ( + (CONST AML_NODE_HEADER*)Node, + (AML_NODE_HEADER**)&NameSpaceNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + Node =3D (CONST AML_OBJECT_NODE*)NameSpaceNode; + ParentCnt =3D 0; + break; + } else { + // The node name has carets. Need to continue climbing the + // AML namespace. + ParentCnt =3D ParentPrefix; + } + } else { + // ParentCnt > SegCount + // NodeName doesn't have enough levels to consume all the ParentCn= t. + // Update ParentCnt: Consume SegCount levels and add ParentPrefix + // levels. Continue climbing the tree. + ParentCnt =3D ParentCnt + ParentPrefix - SegCount; + } + } + } while (ParentCnt !=3D 0); + + *OutNode =3D (CONST AML_NODE_HEADER*)Node; + *Levels =3D ParentCnt; + + return EFI_SUCCESS; +} + +/** Build the raw absolute AML pathname to Node and write it to a stream. + + A raw AML pathname is an AML pathname where the root char ('\'), + prefix chars ('^') and NameString prefix byte (e.g.: DualNamePrefix) + have been removed. A raw AML pathname is a list of concatenated + NameSegs. + + E.g.: + ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0" + AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCC= C" + Raw absolute path: "AAAABBBBCCCC" + + @param [in] Node Node to build the raw absolute path to + Must be a root node, or a namespace node. + @param [in] InputParent Skip InputParent AML namespace levels before + starting building the raw absolute pathname. + E.g.: - Node's name being "^AAAA.BBBB.CCCC"; + - InputParent =3D 2; + "BBBB.CCCC" will be skipped (2 + levels), and "^AAAA" will remain. The + first caret is not related to InputPar= ent. + @param [out] RawAbsPathBStream Backward stream to write the raw + pathname to. + If Node is the root node, the Stream d= ata + Buffer will stay empty. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetRawNameSpacePath ( + IN CONST AML_NODE_HEADER * Node, + IN UINT32 InputParent, + OUT AML_STREAM * RawAbsPathBStream + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * ParentNode; + CHAR8 * NodeName; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + CONST CHAR8 * NameSeg; + + if ((!IS_AML_ROOT_NODE (Node) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE)) || + !IS_STREAM (RawAbsPathBStream) || + IS_END_OF_STREAM (RawAbsPathBStream) || + !IS_STREAM_BACKWARD (RawAbsPathBStream) || + (InputParent > MAX_UINT8)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + while (1) { + if (IS_AML_ROOT_NODE (Node)) { + break; + } + + NodeName =3D AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node); + if (NodeName =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlParseNameStringInfo ( + NodeName, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + if (SegCount > InputParent) { + // 1.1. If the Node's name has enough levels to consume all the + // InputParent carets, write the levels that are left. + NameSeg =3D AmlGetFirstNameSeg (NodeName, Root, ParentPrefix); + Status =3D AmlStreamWrite ( + RawAbsPathBStream, + (CONST UINT8*)NameSeg, + (SegCount - InputParent) * AML_NAME_SEG_SIZE + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + InputParent =3D 0; + } else { + // (SegCount <=3D InputParent) + // 1.2. Else save the InputParent in TotalParent to climb + // them later. + InputParent -=3D SegCount; + } + + InputParent +=3D ParentPrefix; + + if (Root !=3D 0) { + // 2. The Node's name is an absolute path. + // Exit, the root has been reached. + if (InputParent !=3D 0) { + ASSERT (0); + return EFI_NOT_FOUND; + } + break; + } + + Status =3D AmlGetAncestorNameSpaceNode ( + (CONST AML_OBJECT_NODE*)Node, + &InputParent, + &Root, + (CONST AML_NODE_HEADER**)&ParentNode + ); + if (EFI_ERROR (Status) || + (!IS_AML_NODE_VALID (ParentNode))) { + ASSERT (0); + return Status; + } + + Node =3D ParentNode; + + if (IS_AML_ROOT_NODE (Node)) { + // 3.1. If the root node has been found while climbing, + // no need to write NameSegs. + // Exit. + break; + } else if (Root !=3D 0) { + // 3.2. An absolute path has been found while climbing the tree. + // If (InputParent !=3D 0), the raw pathname is not the root. + // Write the first [SegCount - InputParent] NameSegs of this + // absolute path. + // Then exit. + if (InputParent !=3D 0) { + // Get the absolute pathname. + NodeName =3D AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node); + if (NodeName =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Analyze the absolute pathname. + Status =3D AmlParseNameStringInfo ( + NodeName, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Writing the n first NameSegs. + // n =3D SegCount - InputParent + NameSeg =3D AmlGetFirstNameSeg (NodeName, Root, ParentPrefix); + Status =3D AmlStreamWrite ( + RawAbsPathBStream, + (CONST UINT8*)NameSeg, + (SegCount - InputParent) * AML_NAME_SEG_SIZE + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + break; + } // (InputParent !=3D 0) + + } + } // while + + return EFI_SUCCESS; +} + +/** Add the RootChar and prefix byte to the raw AML NameString in the + input Stream to create a valid absolute path. + + The prefix byte can be AML_DUAL_NAME_PREFIX, AML_MULTI_NAME_PREFIX + or nothing. + + @param [in, out] AmlPathBStream The Stream initially contains a raw + NameString (i.e. a list of NameSegs). + The Stream can be empty (e.g.: for the + root path). + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlAddPrefix ( + IN OUT AML_STREAM * AmlPathBStream + ) +{ + EFI_STATUS Status; + UINT32 NameSegCount; + UINT32 NameSegSize; + + // At most 3 bytes are needed for: RootChar + MultiNamePrefix + SegCount. + CHAR8 Prefix[3]; + UINT32 PrefixSize; + + // The Stream contains concatenated NameSegs. + if (!IS_STREAM (AmlPathBStream) || + IS_END_OF_STREAM (AmlPathBStream) || + !IS_STREAM_BACKWARD (AmlPathBStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Its size should be a multiple of AML_NAME_SEG_SIZE. + // AML_NAME_SEG_SIZE =3D 4. Check the 2 lowest bits. + NameSegSize =3D AmlStreamGetIndex (AmlPathBStream); + if ((NameSegSize & (AML_NAME_SEG_SIZE - 1)) !=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Each NameSeg is 4 bytes so divide the NameSegSize by 4. + NameSegCount =3D NameSegSize >> 2; + if (NameSegCount > MAX_UINT8) { + // There can be at most 255 NameSegs. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Prefix[0] =3D AML_ROOT_CHAR; + + switch (NameSegCount) { + case 0: + { + // Root and parents only NameString (no NameSeg(s)) end with '\0'. + Prefix[1] =3D AML_ZERO_OP; + PrefixSize =3D 2; + break; + } + case 1: + { + PrefixSize =3D 1; + break; + } + case 2: + { + Prefix[1] =3D AML_DUAL_NAME_PREFIX; + PrefixSize =3D 2; + break; + } + default: + { + Prefix[1] =3D AML_MULTI_NAME_PREFIX; + Prefix[2] =3D (UINT8)NameSegCount; + PrefixSize =3D 3; + break; + } + } + + // Add the RootChar + prefix (if needed) at the beginning of the pathnam= e. + Status =3D AmlStreamWrite (AmlPathBStream, (CONST UINT8*)Prefix, PrefixS= ize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + return Status; +} + +/** Remove the prefix bytes of an AML NameString stored in a backward stre= am + to get a raw NameString. + + The AML encoding for '\', '^', Dual name or multi-name prefix are + stripped off. + E.g: If the ASL path was "\AAAA.BBBB", the AML equivalent would be + "{RootChar}{DualNamePrefix}AAAABBBB". So resultant raw NameString + is "AAAABBBB". + + @param [in, out] AmlPathBStream Backward stream containing an AML + NameString. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlRemovePrefix ( + IN OUT AML_STREAM * AmlPathBStream + ) +{ + EFI_STATUS Status; + + UINT32 TotalSize; + UINT32 RewindSize; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if (!IS_STREAM (AmlPathBStream) || + IS_END_OF_STREAM (AmlPathBStream) || + !IS_STREAM_BACKWARD (AmlPathBStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlParseNameStringInfo ( + (CHAR8*)AmlStreamGetCurrPos (AmlPathBStream), + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + TotalSize =3D AmlComputeNameStringSize (Root, ParentPrefix, SegCount); + if (TotalSize =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Rewind the stream of all the bytes that are not SegCounts + // to drop the prefix. + RewindSize =3D TotalSize - (SegCount * AML_NAME_SEG_SIZE); + if (RewindSize !=3D 0) { + Status =3D AmlStreamRewind (AmlPathBStream, RewindSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** Build the absolute ASL pathname to Node. + + BufferSize is always updated to the size of the pathname. + + If: + - the content of BufferSize is >=3D to the size of the pathname AND; + - Buffer is not NULL. + then copy the pathname in the Buffer. A buffer of the size + MAX_ASL_NAMESTRING_SIZE is big enough to receive any ASL pathname. + + @param [in] Node Node to build the absolute path to. + Must be a root node, or a namespace no= de. + @param [out] Buffer Buffer to write the path to. + If NULL, only update *BufferSize. + @param [in, out] BufferSize Pointer holding: + - At entry, the size of the Buffer; + - At exit, the size of the pathname. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlGetAslPathName ( + IN AML_NODE_HEADER * Node, + OUT CHAR8 * Buffer, + IN OUT UINT32 * BufferSize + ) +{ + EFI_STATUS Status; + + // Backward stream used to build the raw AML absolute path to the node. + AML_STREAM RawAmlAbsPathBStream; + CHAR8 * RawAmlAbsPathBuffer; + UINT32 RawAmlAbsPathBufferSize; + + CHAR8 * AmlPathName; + CHAR8 * AslPathName; + UINT32 AslPathNameSize; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if ((!IS_AML_ROOT_NODE (Node) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE)) || + (BufferSize =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + AslPathName =3D NULL; + + // Allocate a Stream to get the raw AML absolute pathname. + RawAmlAbsPathBufferSize =3D MAX_AML_NAMESTRING_SIZE; + RawAmlAbsPathBuffer =3D AllocateZeroPool (RawAmlAbsPathBufferSize); + if (RawAmlAbsPathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlStreamInit ( + &RawAmlAbsPathBStream, + (UINT8*)RawAmlAbsPathBuffer, + RawAmlAbsPathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Get the raw pathname of the Node. The raw pathname being an + // AML NameString without the RootChar and prefix byte. + // It is a list of concatenated NameSegs. + Status =3D AmlGetRawNameSpacePath (Node, 0, &RawAmlAbsPathBStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Add the RootChar and prefix byte. + Status =3D AmlAddPrefix (&RawAmlAbsPathBStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + AmlPathName =3D (CHAR8*)AmlStreamGetCurrPos (&RawAmlAbsPathBStream); + + // Analyze the NameString. + Status =3D AmlParseNameStringInfo ( + (CONST CHAR8*)AmlPathName, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Compute the size the ASL pathname will take. + AslPathNameSize =3D AslComputeNameStringSize (Root, ParentPrefix, SegCou= nt); + if (AslPathNameSize =3D=3D 0) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Input Buffer is large enough. Copy the pathname if the Buffer is vali= d. + if ((Buffer !=3D NULL) && (AslPathNameSize <=3D *BufferSize)) { + Status =3D ConvertAmlNameToAslName (AmlPathName, &AslPathName); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status =3D EFI_OUT_OF_RESOURCES; + goto exit_handler; + } + + CopyMem (Buffer, AslPathName, AslPathNameSize); + } + + *BufferSize =3D AslPathNameSize; + +exit_handler: + // Free allocated memory. + FreePool (RawAmlAbsPathBuffer); + if (AslPathName !=3D NULL) { + FreePool (AslPathName); + } + + return Status; +} + +#if !defined (MDEPKG_NDEBUG) + +/** Recursively print the pathnames in the AML namespace in Node's branch. + + @param [in] Node Pointer to a node. + @param [in] Context An empty forward stream holding a pre-alloca= ted + buffer. This prevents from having to do mult= iple + allocations during the enumeration. + @param [in, out] Status At entry, contains the status returned by the + last call to this exact function during the + enumeration. + As exit, contains the returned status of the + call to this function. + Optional, can be NULL. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +STATIC +BOOLEAN +EFIAPI +AmlDbgPrintNameSpaceCallback ( + IN AML_NODE_HEADER * Node, + IN VOID * Context, + IN OUT EFI_STATUS * Status OPTIONAL + ) +{ + BOOLEAN ContinueEnum; + EFI_STATUS Status1; + + AML_STREAM * CurrNodePathFStream; + CHAR8 * CurrNodePathBuffer; + UINT32 CurrNodePathBufferSize; + + ContinueEnum =3D TRUE; + Status1 =3D EFI_SUCCESS; + + if (!IS_AML_NODE_VALID (Node) || + (Context =3D=3D NULL)) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto exit_handler; + } + + if (!IS_AML_ROOT_NODE (Node) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE)) { + // Skip this node and continue enumeration. + goto exit_handler; + } + + if (IS_AML_ROOT_NODE (Node)) { + DEBUG ((DEBUG_INFO, "\\\n")); + } else if (AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE)) { + + CurrNodePathFStream =3D (AML_STREAM*)Context; + + // Check the Context's content. + if (!IS_STREAM (CurrNodePathFStream) || + IS_END_OF_STREAM (CurrNodePathFStream) || + !IS_STREAM_FORWARD (CurrNodePathFStream)) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto exit_handler; + } + + CurrNodePathBuffer =3D (CHAR8*)AmlStreamGetBuffer (CurrNodePathFStream); + CurrNodePathBufferSize =3D AmlStreamGetMaxBufferSize (CurrNodePathFStrea= m); + + Status1 =3D AmlGetAslPathName ( + (AML_NODE_HEADER*)Node, + CurrNodePathBuffer, + &CurrNodePathBufferSize + ); + if (EFI_ERROR (Status1)) { + ASSERT (0); + ContinueEnum =3D FALSE; + goto exit_handler; + } + + DEBUG ((DEBUG_INFO, "%a\n", CurrNodePathBuffer)); + + } else { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + } + +exit_handler: + if (Status !=3D NULL) { + *Status =3D Status1; + } + + return ContinueEnum; +} + +/** Print the absolute pathnames in the AML namespace of + all the nodes in the tree starting from the Root node. + + @param [in] RootNode Pointer to a root node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlDbgPrintNameSpace ( + IN AML_ROOT_NODE * RootNode + ) +{ + EFI_STATUS Status; + + AML_STREAM CurrNodePathFStream; + CHAR8 * CurrNodePathBuffer; + UINT32 CurrNodePathBufferSize; + + if (!IS_AML_ROOT_NODE (RootNode)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "AmlNameSpace: AML namespace:\n")); + + // Allocate memory to build the absolute ASL path to each node. + CurrNodePathBufferSize =3D MAX_AML_NAMESTRING_SIZE; + CurrNodePathBuffer =3D AllocateZeroPool (CurrNodePathBufferSize); + if (CurrNodePathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // An empty forward stream holding a pre-allocated buffer is used + // to avoid multiple allocations during the enumeration. + Status =3D AmlStreamInit ( + &CurrNodePathFStream, + (UINT8*)CurrNodePathBuffer, + CurrNodePathBufferSize, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + AmlEnumTree ( + (AML_NODE_HEADER*)RootNode, + AmlDbgPrintNameSpaceCallback, + (VOID*)&CurrNodePathFStream, + &Status + ); + ASSERT_EFI_ERROR (Status); + +exit_handler: + FreePool (CurrNodePathBuffer); + + return Status; +} + +#endif // MDEPKG_NDEBUG + +/** Callback function to find the node corresponding to an absolute pathna= me. + + For each namespace node, build its raw AML absolute path. Then compare t= his + path with the raw AML absolute path of the search node available in the + Context. + + @param [in] Node Pointer to the node to whose pathname is bei= ng + tested. + @param [in, out] Context A pointer to AML_PATH_SEARCH_CONTEXT that ha= s: + - The searched path stored in a stream; + - An empty stream to query the pathname of = the + probed node; + - A node pointer to store the searched node + if found. + @param [in, out] Status At entry, contains the status returned by the + last call to this exact function during the + enumeration. + As exit, contains the returned status of the + call to this function. + Optional, can be NULL. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +STATIC +BOOLEAN +EFIAPI +AmlEnumeratePathCallback ( + IN AML_NODE_HEADER * Node, + IN OUT VOID * Context, + IN OUT EFI_STATUS * Status OPTIONAL +) +{ + BOOLEAN ContinueEnum; + EFI_STATUS Status1; + + AML_PATH_SEARCH_CONTEXT * PathSearchContext; + + AML_STREAM * SearchPathBStream; + CHAR8 * SearchedPath; + + AML_STREAM * CurrNodePathBStream; + CHAR8 * CurrNodePath; + UINT32 CurrNodePathSize; + + ContinueEnum =3D TRUE; + Status1 =3D EFI_SUCCESS; + + if (!IS_AML_NODE_VALID (Node) || + (Context =3D=3D NULL)) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto exit_handler; + } + + if (!AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE)) { + goto exit_handler; + } + + PathSearchContext =3D (AML_PATH_SEARCH_CONTEXT*)Context; + SearchPathBStream =3D PathSearchContext->SearchPathBStream; + CurrNodePathBStream =3D PathSearchContext->CurrNodePathBStream; + + // Check the Context's content. + if (!IS_STREAM (SearchPathBStream) || + IS_END_OF_STREAM (SearchPathBStream) || + !IS_STREAM_BACKWARD (SearchPathBStream) || + !IS_STREAM (CurrNodePathBStream) || + IS_END_OF_STREAM (CurrNodePathBStream) || + !IS_STREAM_BACKWARD (CurrNodePathBStream)) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto exit_handler; + } + + CurrNodePathSize =3D AmlStreamGetMaxBufferSize (CurrNodePathBStream); + if (CurrNodePathSize =3D=3D 0) { + ASSERT (0); + Status1 =3D EFI_INVALID_PARAMETER; + ContinueEnum =3D FALSE; + goto exit_handler; + } + + SearchedPath =3D (CHAR8*)AmlStreamGetCurrPos (SearchPathBStream); + CurrNodePath =3D (CHAR8*)AmlStreamGetCurrPos (CurrNodePathBStream); + + // Get the raw AML absolute pathname of the current node. + Status1 =3D AmlGetRawNameSpacePath (Node, 0, CurrNodePathBStream); + if (EFI_ERROR (Status1)) { + ASSERT (0); + ContinueEnum =3D FALSE; + goto exit_handler; + } + + DEBUG (( + DEBUG_VERBOSE, + "AmlNameSpace: " + "Comparing search path with current node path.\n" + )); + DEBUG ((DEBUG_VERBOSE, "Search path:")); + AmlDbgPrintChars ( + DEBUG_VERBOSE, + (CHAR8*)AmlStreamGetCurrPos (SearchPathBStream), + AmlStreamGetIndex (SearchPathBStream) + ); + DEBUG ((DEBUG_VERBOSE, "\nPath of the current node: ")); + AmlDbgPrintChars ( + DEBUG_VERBOSE, + (CHAR8*)AmlStreamGetCurrPos (CurrNodePathBStream), + AmlStreamGetIndex (CurrNodePathBStream) + ); + DEBUG ((DEBUG_VERBOSE, "\n")); + + // Compare the searched path and Node's path. + if ((AmlStreamGetIndex (CurrNodePathBStream) =3D=3D + AmlStreamGetIndex (SearchPathBStream)) && + (CompareMem ( + AmlStreamGetCurrPos (CurrNodePathBStream), + AmlStreamGetCurrPos (SearchPathBStream), + AmlStreamGetIndex (SearchPathBStream)) =3D=3D 0)) { + Status1 =3D EFI_SUCCESS; + ContinueEnum =3D FALSE; + PathSearchContext->OutNode =3D Node; + } else { + // If the paths don't match, reset the CurrNodePathStream's content. + Status1 =3D AmlStreamReset (CurrNodePathBStream); + if (EFI_ERROR (Status1)) { + ASSERT (0); + ContinueEnum =3D FALSE; + } + } + +exit_handler: + if (Status !=3D NULL) { + *Status =3D Status1; + } + + return ContinueEnum; +} + +/** Build a raw AML absolute path from a reference node and a relative + ASL path. + + The AslPath can be a relative path or an absolute path. + Node must be a root node or a namespace node. + A root node is expected to be at the top of the tree. + + @param [in] ReferenceNode Reference node. + If a relative path is given, t= he + search is done from this node.= If + an absolute path is given, the + search is done from the root n= ode. + Must be a root node or an obje= ct + node which is part of the + namespace. + @param [in] AslPath ASL path to the searched node = in + the namespace. An ASL path nam= e is + NULL terminated. Can be a rela= tive + or absolute path. + E.g.: "\\_SB.CLU0.CPU0". + @param [in, out] RawAmlAbsSearchPathBStream Backward stream to write t= he + raw absolute AML path of t= he + searched node. + The stream must not be at + its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlBuildAbsoluteAmlPath ( + IN AML_NODE_HEADER * ReferenceNode, + IN CHAR8 * AslPath, + IN OUT AML_STREAM * RawAmlAbsSearchPathBStream + ) +{ + EFI_STATUS Status; + CHAR8 * AmlPath; + + UINT32 AmlNameStringSize; + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if ((!IS_AML_ROOT_NODE (ReferenceNode) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ReferenceNode, + AML_IN_NAMESPACE)) || + (AslPath =3D=3D NULL) || + !IS_STREAM (RawAmlAbsSearchPathBStream) || + IS_END_OF_STREAM (RawAmlAbsSearchPathBStream) || + !IS_STREAM_BACKWARD (RawAmlAbsSearchPathBStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // 1. Validate, analyze and convert the AslPath to an AmlPath. + Status =3D ConvertAslNameToAmlName (AslPath, &AmlPath); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlParseNameStringInfo (AmlPath, &Root, &ParentPrefix, &SegCo= unt); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Not possible to go beyond the root. + if (IS_AML_ROOT_NODE (ReferenceNode) && (ParentPrefix !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + ASSERT (0); + goto exit_handler; + } + + AmlNameStringSize =3D AmlComputeNameStringSize (Root, ParentPrefix, SegC= ount); + if (AmlNameStringSize =3D=3D 0) { + Status =3D EFI_INVALID_PARAMETER; + ASSERT (0); + goto exit_handler; + } + + // 2.1. Write the AML path to the stream. + Status =3D AmlStreamWrite ( + RawAmlAbsSearchPathBStream, + (CONST UINT8*)AmlPath, + AmlNameStringSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // 2.2. Then remove the AML prefix (root char, parent prefix, etc.) + // to obtain a raw AML NameString. Raw AML NameString are easier + // to manipulate. + Status =3D AmlRemovePrefix (RawAmlAbsSearchPathBStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // 3. If AslPath is a relative path and the reference Node is not + // the root node, fill the Stream with the absolute path to the + // reference node. + if ((Root =3D=3D 0) && !IS_AML_ROOT_NODE (ReferenceNode)) { + Status =3D AmlGetRawNameSpacePath ( + ReferenceNode, + ParentPrefix, + RawAmlAbsSearchPathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } + +exit_handler: + // Free allocated memory. + FreePool (AmlPath); + + return Status; +} + +/** Find a node in the AML namespace, given an ASL path and a reference No= de. + + - The AslPath can be an absolute path, or a relative path from the + reference Node; + - Node must be a root node or a namespace node; + - A root node is expected to be at the top of the tree. + + E.g.: + For the following AML namespace, with the ReferenceNode being the node w= ith + the name "AAAA": + - the node with the name "BBBB" can be found by looking for the ASL + path "BBBB"; + - the root node can be found by looking for the ASL relative path "^", + or the absolute path "\\". + + AML namespace: + \ + \-AAAA <- ReferenceNode + \-BBBB + + @param [in] ReferenceNode Reference node. + If a relative path is given, the + search is done from this node. If + an absolute path is given, the + search is done from the root node. + Must be a root node or an object + node which is part of the + namespace. + @param [in] AslPath ASL path to the searched node in + the namespace. An ASL path name is + NULL terminated. Can be a relative + or absolute path. + E.g.: "\\_SB.CLU0.CPU0" or "^CPU0" + @param [out] OutNode Pointer to the found node. + Contains NULL if not found. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlFindNode ( + IN AML_NODE_HEADER * ReferenceNode, + IN CHAR8 * AslPath, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + + AML_PATH_SEARCH_CONTEXT PathSearchContext; + AML_ROOT_NODE * RootNode; + + // Backward stream used to build the raw AML absolute path to the search= ed + // node. + AML_STREAM RawAmlAbsSearchPathBStream; + CHAR8 * RawAmlAbsSearchPathBuffer; + UINT32 RawAmlAbsSearchPathBufferSize; + + // Backward stream used to store the raw AML absolute path of the node + // currently enumerated in the tree. This path can then be compared to t= he + // RawAmlAbsSearchPath. + AML_STREAM RawAmlAbsCurrNodePathBStream; + CHAR8 * RawAmlAbsCurrNodePathBuffer; + UINT32 RawAmlAbsCurrNodePathBufferSize; + + if ((!IS_AML_ROOT_NODE (ReferenceNode) && + !AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ReferenceNode, + AML_IN_NAMESPACE)) || + (AslPath =3D=3D NULL) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutNode =3D NULL; + RawAmlAbsCurrNodePathBuffer =3D NULL; + + // 1. Build a raw absolute AML path from the reference node and the ASL + // path. For this: + // 1.1. First initialize a backward stream. + RawAmlAbsSearchPathBufferSize =3D MAX_AML_NAMESTRING_SIZE; + RawAmlAbsSearchPathBuffer =3D AllocateZeroPool (RawAmlAbsSearchPathBuffe= rSize); + if (RawAmlAbsSearchPathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlStreamInit ( + &RawAmlAbsSearchPathBStream, + (UINT8*)RawAmlAbsSearchPathBuffer, + RawAmlAbsSearchPathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // 1.2. Then build the raw AML absolute path. + Status =3D AmlBuildAbsoluteAmlPath ( + ReferenceNode, + AslPath, + &RawAmlAbsSearchPathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // 2. Find the root node by climbing up the tree from the reference node. + RootNode =3D AmlGetRootNode (ReferenceNode); + if (RootNode =3D=3D NULL) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // 3. If the searched node is the root node, return. + // For the Root Node there is no NameSegs so the length of + // the stream will be zero. + if (AmlStreamGetIndex (&RawAmlAbsSearchPathBStream) =3D=3D 0) { + *OutNode =3D (AML_NODE_HEADER*)RootNode; + Status =3D EFI_SUCCESS; + goto exit_handler; + } + + // 4. Create a backward stream large enough to hold the current node path + // during enumeration. This prevents from doing multiple allocation/f= ree + // operations. + RawAmlAbsCurrNodePathBufferSize =3D MAX_ASL_NAMESTRING_SIZE; + RawAmlAbsCurrNodePathBuffer =3D AllocateZeroPool ( + RawAmlAbsCurrNodePathBufferSize + ); + if (RawAmlAbsCurrNodePathBuffer =3D=3D NULL) { + ASSERT (0); + Status =3D EFI_OUT_OF_RESOURCES; + goto exit_handler; + } + + Status =3D AmlStreamInit ( + &RawAmlAbsCurrNodePathBStream, + (UINT8*)RawAmlAbsCurrNodePathBuffer, + RawAmlAbsCurrNodePathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // 5. Fill a path search context structure with: + // - SearchPathStream: backward stream containing the raw absolute A= ML + // path to the searched node; + // - CurrNodePathStream: backward stream containing the raw absolute= AML + // of the node currently being enumerated; + // - OutNode: node pointer to the store the potentially found node. + PathSearchContext.SearchPathBStream =3D &RawAmlAbsSearchPathBStream; + PathSearchContext.CurrNodePathBStream =3D &RawAmlAbsCurrNodePathBStream; + PathSearchContext.OutNode =3D NULL; + + // 6. Iterate through the namespace nodes of the tree. + // For each namespace node, build its raw AML absolute path. Then com= pare + // it with the search path. + AmlEnumTree ( + (AML_NODE_HEADER*)RootNode, + AmlEnumeratePathCallback, + (VOID*)&PathSearchContext, + &Status + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + *OutNode =3D PathSearchContext.OutNode; + if (*OutNode =3D=3D NULL) { + Status =3D EFI_NOT_FOUND; + } + +exit_handler: + // Free allocated memory. + FreePool (RawAmlAbsSearchPathBuffer); + if (RawAmlAbsCurrNodePathBuffer !=3D NULL) { + FreePool (RawAmlAbsCurrNodePathBuffer); + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.= h b/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h new file mode 100644 index 0000000000000000000000000000000000000000..3d8ebc8b182983606af7e7ddfe3= 078fd729fb5b6 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h @@ -0,0 +1,74 @@ +/** @file + AML NameSpace. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_NAMESPACE_H_ +#define AML_NAMESPACE_H_ + +#include +#include + +/** Return the first AML namespace node up in the parent hierarchy. + + Return the root node if no namespace node is found is the hierarchy. + + @param [in] Node Node to look at the parents from. + If Node is the root node, OutNode is NULL. + @param [out] OutNode If a namespace node is found, pointer to the + first namespace node of Node's parents. + Stop at the root node otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + **/ +EFI_STATUS +EFIAPI +AmlGetFirstAncestorNameSpaceNode ( + IN CONST AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** OutNode + ); + +/** Build the raw absolute AML pathname to Node and write it to a stream. + + A raw AML pathname is an AML pathname where the root char ('\'), + prefix chars ('^') and NameString prefix byte (e.g.: DualNamePrefix) + have been removed. A raw AML pathname is a list of concatenated + NameSegs. + + E.g.: + ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0" + AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCC= C" + Raw absolute path: "AAAABBBBCCCC" + + @param [in] Node Node to build the raw absolute path to + Must be a root node, or a namespace node. + @param [in] InputParent Skip InputParent AML namespace levels before + starting building the raw absolute pathname. + E.g.: - Node's name being "^AAAA.BBBB.CCCC"; + - InputParent =3D 2; + "BBBB.CCCC" will be skipped (2 + levels), and "^AAAA" will remain. The + first caret is not related to InputPar= ent. + @param [out] RawAbsPathBStream Backward stream to write the raw + pathname to. + If Node is the root node, the Stream d= ata + Buffer will stay empty. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetRawNameSpacePath ( + IN CONST AML_NODE_HEADER * Node, + IN UINT32 InputParent, + OUT AML_STREAM * RawAbsPathBStream + ); + +#endif // AML_NAMESPACE_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64093): https://edk2.groups.io/g/devel/message/64093 Mute This Topic: https://groups.io/mt/76149169/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64095+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 159724583411298.22261187852325; Wed, 12 Aug 2020 08:23:54 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id fZzBYY1788612xa8lT0UpiVb; Wed, 12 Aug 2020 08:23:53 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.74]) by mx.groups.io with SMTP id smtpd.web10.17199.1597245823400237301 for ; Wed, 12 Aug 2020 08:23:44 -0700 X-Received: from MR2P264CA0072.FRAP264.PROD.OUTLOOK.COM (2603:10a6:500:31::36) by AM7PR08MB5352.eurprd08.prod.outlook.com (2603:10a6:20b:10e::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com (2603:10a6:500:31:cafe::fb) by MR2P264CA0072.outlook.office365.com (2603:10a6:500:31::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64095+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT028.mail.protection.outlook.com (10.152.18.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:39 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 6f450c2b185c799c X-CR-MTA-TID: 64aa7808 X-Received: from 82f8f287aae6.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 50A7306F-AB5A-408F-953E-71A897A23021.1; Wed, 12 Aug 2020 15:23:34 +0000 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 82f8f287aae6.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:34 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JrDV2Y+yXpu/d6Ipgw0SJ6kXnDl1ig9/B26U5hXXzcoah/e40se2v31MSPUcCMje9puvDle9jQlBNDCocBJ5JNEbcTvZ8b8varOIlqlqHtIKNeh2tUy/PXL9OjdulMa9JLjjD4c6zcYLh2GuQvjK4lfnEbn7/X2tHKuXZ9HMM46mS/uzgrqYb55+9U3qmQ6vTYqwU9rxJmgbqcLwSkhOe7w4Sq3pTAe1hkK/xi/x//qsdQycPcs0ArCvYecapARUDTvmiAo1sahsUFH1MPPuZg4iSiVtIT7nEaNwZkVMXvpwnqcU+hXKh0EsSgliBgq3U6O9qZ/gFRq7HsnnvTo6/A== 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-SenderADCheck; bh=IVNun+Buxaf5BPa12/jO4Ih/grQY3OeHiVBnROQ/h8k=; b=Mafy/EdySxanL4ji9N5uHxpsPQ3SQ9VvVTysjUh6vEisc2fnZ0GECp6z7sd/1NhmF9B7xMTbLgeh0UgWG2M8x4c6lIqXy1yNgS1km1IZdgx8le46RhbC47o9mHg1aNa+sHIWvL8GPx7pbu4+OEGvNWSqpk+TEqfsSHBcJJ4KZn0WhtPr9XGB9CScMrzBUcGIWFXB6IXjDzNOs79E8dxr+D35RwcLeP0jnMEjiKw9EA9Aqv8pRyirg2D8q104P1Z5Fi77nZ39SXHoA4QFq/n82MFWG6BakXx8irtJgz1woP5P+/BR0T8MCdBEByjGHqLN1dFQEWOR2clleFl0LiPRHQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM0PR03CA0059.eurprd03.prod.outlook.com (2603:10a6:208::36) by AM5PR0801MB1988.eurprd08.prod.outlook.com (2603:10a6:203:48::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from AM5EUR03FT060.eop-EUR03.prod.protection.outlook.com (2603:10a6:208:0:cafe::60) by AM0PR03CA0059.outlook.office365.com (2603:10a6:208::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT060.mail.protection.outlook.com (10.152.16.160) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:30 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:27 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:27 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 16/30] DynamicTablesPkg: AML Parser Date: Wed, 12 Aug 2020 16:22:22 +0100 Message-ID: <20200812152236.31164-17-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: b8b8c697-0202-4985-974b-08d83ed3b0bd X-MS-TrafficTypeDiagnostic: AM5PR0801MB1988:|AM7PR08MB5352: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:6108;OLM:6108; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: /wlCxmPaL4JL0fNxBQllc54tiGcGBdbuWdxSac+WLlyTKwlTDm9mMzqXRLm/rAAhphgBF31x3pJsIZGRBo9cdfiHJnKFHMmpXzYKdaASWDMgJkJzger7d3rMwA4/yiU4sH/4V1rfAkt873CrmE057BfJ4LKqbsxEgLeg+S5zvQkxkTAG4K8LDr+vtWSEwr2gEgHwI3CXhiTxunfbcqaReqZy3byQn46vJWL6WICv9Qpcpcfu82s7jNOdk3yFywKfVFMMGH6DyZCt6Nx8/MgAspu2rChOoebRtn/OsDUyORk2GDu1gGRGNFy9gKlB078DuAIsARSCbBYYAMi3jXnZY5MU+fDoncvKumeezUVli/g7dk8SxXi9TlUX31Btu5kuVoAscMzBjIGsgEh8WcLtKA== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(39860400002)(136003)(396003)(376002)(346002)(46966005)(8676002)(316002)(47076004)(54906003)(82740400003)(30864003)(1076003)(5660300002)(86362001)(6666004)(70586007)(70206006)(336012)(4326008)(82310400002)(2616005)(8936002)(2906002)(6916009)(36756003)(26005)(83380400001)(478600001)(81166007)(356005)(7696005)(186003)(426003)(44832011)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1988 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 8ec7bfe2-801d-47cb-a82b-08d83ed3aba0 X-Microsoft-Antispam-Message-Info: CUTExzS+IflTR55EQxBz6DngoRpsx/bjhfNP8vCVXyZYkhdZG2xSK57gRN7gpLQpvXc/CiMH8Aa/9CpiUzvOk4amkDlh1HHmF70sHJFj/K/1I4XtxO5Iaro4E7IVXL8KHZQ30IcUdItvw/X5gWMSbb1ZDuxfH5RCxslDwZtZW4lzdaGBE7Dv+MBgJ8vbYE+Y82mQUBP3kWjmgJD5ve6Tdr3DW/1hswCC2AdukFo9SVaJkgK1EFcoIgqm0aQaZPcgxEAL57pVbCF9b1v50yty1njtmbqMYF+5fPTOb3hj5V7lYEZPDsV7M6sSsKcWBwM8lmzmBFtR3a312k4X8lVdhFAoUI5rXMb+Iyr2o03jt4DvCeCiIk2BFgq7ktplPogK5yuA4RPQEt4/aSwu87O3OQ== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:39.5682 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b8b8c697-0202-4985-974b-08d83ed3b0bd 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: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM7PR08MB5352 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: K8EvEyw7lUMApzoWYQPI8zybx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245833; bh=YRmA/cIhz+QTF77Si7Zx5NwUQpF1ibkvwvzSVaUFjTE=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=KShN8/sx+EC3lPFHtbaXjHsW9MAx1eyWwtC49Yh0GQROetl8uTFpx8Tjw8Vw9wy5xyz X2p2PQJ3tI1Yp1fww83GwmTvFy/Cf898N7zT8NxRutO/Yv0xqLX9NI8TgMKXQAyTTovDk ZAczXSZORoYFjAQ0zLmwhF0GYY8QQ0M0whE= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Both ASL and AML are declarative language. The ASL code is compiled to AML bytecode. The AML bytecode is processed by the ACPI AML interpreter that runs as part of an OS. AML has a complex encoding making dynamic generation of Definition Block tables difficult. Dynamic AML generation involves techniques like AML Fixup and AML Codegen, both requiring parsing of AML bytecode. The AML parser is a module that parses an AML byte stream and represents it as an AML tree. Representing the AML bytecode as an AML tree is key to reducing the complexity and enabling Dynamic AML generation. In an AML Tree each AML statement (that also corresponds to an ASL statement) is represented as an 'Object Node'. Each Object Node has an OpCode and up to 6 Fixed Arguments followed by a list of Variable Arguments. (ObjectNode) \ |- [0][1][2][3][4][5] # Fixed Arguments |- {(VarArg1)->(VarArg2)->...N} # Variable Arguments A Fixed Argument or Variable Argument can be either an Object Node or a Data Node. A 'Data Node' consists of a data buffer. A 'Root Node' is a special type of Object Node that does not have an Opcode or Fixed Arguments. It only has a list of Variable Arguments. The Root Node is at the top of the AML tree and contains the Definition Block Header. The AML parser uses the 'AML Encoding' to parse an AML byte stream and represents it as an AML Tree. Representing in the form of an AML tree simplifies modification, addition and removal of the tree nodes. The modified tree can then be serialised to a buffer representing a Definition Block table. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c | 1448 +++++++++= +++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h | 72 + 2 files changed, 1520 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c b/Dy= namicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c new file mode 100644 index 0000000000000000000000000000000000000000..380ac9bbcebef01d1d1f5dbd019= 71992aaf66d89 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c @@ -0,0 +1,1448 @@ +/** @file + AML Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + AML Tree + -------- + + Each ASL Statement is represented in AML as and ObjectNode. + Each ObjectNode has an Opcode and has up to six FixedArguments + followed by a list of VariableArguments. + (ObjectNode) + \ + |- [0][1][2][3][4][5] # Fixed Arguments + |- {(VarArg1)->(VarArg2)->(VarArg3)->...N} # Variable Arguments + + A RootNode is a special type of Object Node that does not have an + Opcode or Fixed Arguments. It only has a list of VariableArguments + (RootNode) + \ + |- {(VarArg1)->(VarArg2)->(VarArg3)->...N} # Variable Arguments + + A DataNode consists of a data buffer. + + A FixedArgument or VariableArgument can be either an ObjectNode or + a DataNode. + + Example: + ASL code sample: + Device (DEV0) { + Name (VAR0, 0x6) + } + + Tree generated from the ASL code: + (RootNode) + \ + |- {(Device statement (ObjectNode))} # Variable Arg of = the + \ # RootNode + | + |- [0] - Device Name (DataNode)(=3D"DEV0") # Fixed Arg0 of = the + | # Device() state= ment + | + |- {(Name statement (ObjectNode))} # Variable Arg of = the + \ # Device() state= ment + | + |- [0] - Name statement(DataNode)(=3D"VAR0") # Fixed Arg0= of the + | # Name() sta= tement + |- [1] - Value(DataNode)(=3D0x6) # Fixed Arg1= of the + # Name() sta= tement +*/ + +// Forward declaration. +STATIC +EFI_STATUS +EFIAPI +AmlParseStream ( + IN AML_NODE_HEADER * Node, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList + ); + +/** Function pointer to parse an AML construct. + + The expected format of the AML construct is passed in the + ExpectedFormat argument. The available formats are available in + the AML_PARSE_FORMAT enum definition. + + An object node or a data node is created in the function, + and returned through the OutNode parameter. This node should + be attached after this function returns. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +typedef +EFI_STATUS +EFIAPI +(*AML_PARSE_FUNCTION) ( + IN CONST AML_NODE_HEADER * Node, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ); + +/** Parse a UInt (where X=3D8, 16, 32 or 64). + + A data node is created and returned through the OutNode parameter. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseUIntX ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + UINT32 UIntXSize; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + ((ExpectedFormat !=3D EAmlUInt8) && + (ExpectedFormat !=3D EAmlUInt16) && + (ExpectedFormat !=3D EAmlUInt32) && + (ExpectedFormat !=3D EAmlUInt64)) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + switch (ExpectedFormat) { + case EAmlUInt8: + UIntXSize =3D 1; + break; + case EAmlUInt16: + UIntXSize =3D 2; + break; + case EAmlUInt32: + UIntXSize =3D 4; + break; + case EAmlUInt64: + UIntXSize =3D 8; + break; + default: + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCreateDataNode ( + AmlTypeToNodeDataType (ExpectedFormat), + AmlStreamGetCurrPos (FStream), + UIntXSize, + (AML_DATA_NODE**)OutNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + DumpRaw (AmlStreamGetCurrPos (FStream), UIntXSize); + + // Move stream forward by the size of UIntX. + Status =3D AmlStreamProgress (FStream, UIntXSize); + if (EFI_ERROR (Status)) { + AmlDeleteTree (*OutNode); + ASSERT (0); + } + + return Status; +} + +/** Parse an AML NameString. + + A data node is created and returned through the OutNode parameter. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseNameString ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + + CONST UINT8 * Buffer; + CONST AML_BYTE_ENCODING * ByteEncoding; + UINT32 StrSize; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (ExpectedFormat !=3D EAmlName) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + ByteEncoding =3D AmlGetByteEncoding (Buffer); + if ((ByteEncoding =3D=3D NULL) || + ((ByteEncoding->Attribute & AML_IS_NAME_CHAR) =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the NameString. + Status =3D AmlGetNameStringSize ((CONST CHAR8*)Buffer, &StrSize); + if ((EFI_ERROR (Status)) || + (StrSize > AmlStreamGetFreeSpace (FStream))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeNameString, + Buffer, + StrSize, + (AML_DATA_NODE**)OutNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + DumpRaw (AmlStreamGetCurrPos (FStream), StrSize); + + // Move the stream forward by StrSize. + Status =3D AmlStreamProgress (FStream, StrSize); + if (EFI_ERROR (Status)) { + AmlDeleteTree (*OutNode); + ASSERT (0); + } + + return Status; +} + +/** Parse an AML String. + + A data node is created and returned through the OutNode parameter. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseString ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + UINT32 StrSize; + UINT8 Byte; + CONST UINT8 * Buffer; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (ExpectedFormat !=3D EAmlString) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + StrSize =3D 0; + // AML String is NULL terminated. + do { + // Reading the stream moves the stream forward aswell. + Status =3D AmlStreamReadByte (FStream, &Byte); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + StrSize++; + } while (Byte !=3D '\0'); + + DumpRaw (Buffer, StrSize); + + Status =3D AmlCreateDataNode ( + AmlTypeToNodeDataType (ExpectedFormat), + Buffer, + StrSize, + (AML_DATA_NODE**)OutNode + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Parse an AML object. + + An object can be resolved as an AML object with an OpCode, + or a NameString. An object node or a data node is created + and returned through the OutNode parameter. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseObject ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + + UINT8 OpCodeSize; + UINT32 PkgLength; + UINT32 PkgOffset; + UINT32 FreeSpace; + + CONST AML_BYTE_ENCODING * AmlByteEncoding; + CONST UINT8 * Buffer; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (ExpectedFormat !=3D EAmlObject) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + PkgLength =3D 0; + + // 0. Get the AML Byte encoding. + AmlByteEncoding =3D AmlGetByteEncoding (AmlStreamGetCurrPos (FStream)); + if (AmlByteEncoding =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // 1. Check for NameString. + // Indeed a NameString can be found when an AML object is expected. + // e.g. VAR0 =3D 3 // VAR0 is assigned an object which is a U= INT. + // VAR1 =3D VAR2 // VAR2 is a NameString. + // If this is a NameString, return. A NameString can be a variable, a + // method invocation, etc. + if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) !=3D 0) { + Status =3D AmlParseNameString ( + ParentNode, + EAmlName, + FStream, + OutNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + return Status; + } + + // 2. Determine the OpCode size to move the stream forward. + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + if (*Buffer =3D=3D AML_EXT_OP) { + OpCodeSize =3D 2; + } else { + OpCodeSize =3D 1; + } + Status =3D AmlStreamProgress (FStream, OpCodeSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Print the opcode. + DumpRaw (Buffer, OpCodeSize); + + if (!IS_END_OF_STREAM (FStream)) { + // 3. Parse the PkgLength field, if present. + if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) !=3D 0) { + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + PkgOffset =3D AmlGetPkgLength (Buffer, &PkgLength); + if (PkgOffset =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Print the package length. + DumpRaw (Buffer, PkgOffset); + + // Adjust the size of the stream if it is valid package length. + FreeSpace =3D AmlStreamGetFreeSpace (FStream); + if (FreeSpace > PkgLength) { + // Reduce the stream size by (FreeSpace - PkgLength) bytes. + AmlStreamReduceMaxBufferSize (FStream, FreeSpace - PkgLength); + } else if (FreeSpace !=3D PkgLength) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlStreamProgress (FStream, PkgOffset); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } else if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) !=3D 0) { + // The stream terminated unexpectedly. A PkgLen had to be parsed. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // 4. Create an Object Node. + Status =3D AmlCreateObjectNode ( + AmlByteEncoding, + PkgLength, + (AML_OBJECT_NODE**)OutNode + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Parse a FieldPkgLen. + + A FieldPkgLen can only be found in a field list, i.e. in a NamedField fi= eld + element. The PkgLen is otherwise part of the object node structure. + A data node is created and returned through the OutNode parameter. + + @param [in] ParentNode Parent node to which the parsed + AML construct will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML byte= code + to parse. + The stream must not be at its end. + @param [out] OutNode Pointer holding the node created from = the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseFieldPkgLen ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + CONST UINT8 * Buffer; + UINT32 PkgOffset; + UINT32 PkgLength; + + if (!AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ParentNode, + AML_IS_FIELD_ELEMENT + ) || + (ExpectedFormat !=3D EAmlFieldPkgLen) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + + PkgOffset =3D AmlGetPkgLength (Buffer, &PkgLength); + if (PkgOffset =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Warning: Since, updating of field elements is not supported, store the + // FieldPkgLength in a Data Node as a raw buffer. + Status =3D AmlCreateDataNode ( + AmlTypeToNodeDataType (ExpectedFormat), + Buffer, + PkgOffset, + (AML_DATA_NODE**)OutNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + DumpRaw (Buffer, PkgOffset); + + Status =3D AmlStreamProgress (FStream, PkgOffset); + if (EFI_ERROR (Status)) { + Status1 =3D AmlDeleteNode (*OutNode); + ASSERT_EFI_ERROR (Status1); + ASSERT (0); + } + + return Status; +} + +/** Array of functions pointers to parse the AML constructs. + + The AML Byte encoding tables in Aml.c describe the format of the AML + statements. The AML_PARSE_FORMAT enum definition lists these constructs + and the corresponding parsing functions. +*/ +AML_PARSE_FUNCTION mParseType[EAmlParseFormatMax] =3D { + NULL, // EAmlNone + AmlParseUIntX, // EAmlUInt8 + AmlParseUIntX, // EAmlUInt16 + AmlParseUIntX, // EAmlUInt32 + AmlParseUIntX, // EAmlUInt64 + AmlParseObject, // EAmlObject + AmlParseNameString, // EAmlName + AmlParseString, // EAmlString + AmlParseFieldPkgLen // EAmlFieldPkgLen +}; + +/** Check whether the NameString stored in the data node is a method invoc= ation. + If so, create a method invocation node and return it. + + @param [in] ParentNode Node to which the parsed AML constru= ct + will be attached. + @param [in] DataNode Data node containing a NameString, + potentially being a method invocatio= n. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + @param [out] OutNode Pointer holding the method invocation + node if the NameString contained in = the + data node is a method invocation. + NULL otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCheckAndParseMethodInvoc ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_DATA_NODE * DataNode, + IN OUT LIST_ENTRY * NameSpaceRefList, + OUT AML_OBJECT_NODE ** OutNode + ) +{ + EFI_STATUS Status; + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + AML_OBJECT_NODE * MethodInvocationNode; + AML_STREAM FStream; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + !IS_AML_DATA_NODE (DataNode) || + (DataNode->DataType !=3D EAmlNodeDataTypeNameString) || + (NameSpaceRefList =3D=3D NULL) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Initialize a stream containing the NameString which is checked. + Status =3D AmlStreamInit ( + &FStream, + DataNode->Buffer, + DataNode->Size, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Check whether the NameString is a method invocation. + NameSpaceRefNode =3D NULL; + Status =3D AmlIsMethodInvocation ( + ParentNode, + &FStream, + NameSpaceRefList, + &NameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + MethodInvocationNode =3D NULL; + if (NameSpaceRefNode !=3D NULL) { + // A matching method definition has been found. + // Create a method invocation node. + Status =3D AmlCreateMethodInvocationNode ( + NameSpaceRefNode, + (AML_DATA_NODE*)DataNode, + &MethodInvocationNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + *OutNode =3D MethodInvocationNode; + + return EFI_SUCCESS; +} + +/** Call the appropriate function to parse the AML construct in the stream. + + The ExpectedFormat parameter allows to choose the right parsing function. + An object node or a data node is created according to format. + + @param [in] ParentNode Node to which the parsed AML constru= ct + will be attached. + @param [in] ExpectedFormat Format of the AML construct to parse. + @param [in, out] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + @param [out] OutNode Pointer holding the node created fro= m the + parsed AML bytecode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseArgument ( + IN CONST AML_NODE_HEADER * ParentNode, + IN AML_PARSE_FORMAT ExpectedFormat, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList, + OUT AML_NODE_HEADER ** OutNode + ) +{ + EFI_STATUS Status; + AML_PARSE_FUNCTION ParsingFunction; + AML_DATA_NODE * DataNode; + AML_OBJECT_NODE * MethodInvocationNode; + + if ((!IS_AML_ROOT_NODE (ParentNode) && + !IS_AML_OBJECT_NODE (ParentNode)) || + (ExpectedFormat >=3D EAmlParseFormatMax) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL) || + (OutNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ParsingFunction =3D mParseType[ExpectedFormat]; + if (ParsingFunction =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Note: The ParsingFunction moves the stream forward as it + // consumes the AML bytecode + Status =3D ParsingFunction ( + ParentNode, + ExpectedFormat, + FStream, + OutNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Check whether the parsed argument is a NameString when an object + // is expected. In such case, it could be a method invocation. + DataNode =3D (AML_DATA_NODE*)*OutNode; + if (IS_AML_DATA_NODE (DataNode) && + (DataNode->DataType =3D=3D EAmlNodeDataTypeNameString) && + (ExpectedFormat =3D=3D EAmlObject)) { + Status =3D AmlCheckAndParseMethodInvoc ( + ParentNode, + (AML_DATA_NODE*)*OutNode, + NameSpaceRefList, + &MethodInvocationNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // A method invocation node has been created and the DataNode containi= ng + // the NameString has been attached to the MethodInvocationNode. + // Replace the OutNode with the MethodInvocationNode. + if (MethodInvocationNode !=3D NULL) { + *OutNode =3D (AML_NODE_HEADER*)MethodInvocationNode; + } + } + + return Status; +} + +/** Parse the Bytelist in the stream. + According to the content of the stream, create data node(s) + and add them to the variable list of arguments. + The byte list may be a list of resource data element or a simple byte = list. + + @param [in] BufferNode Object node having a byte list. + @param [in, out] FStream Forward stream containing the AML bytecode + to parse. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlParseByteList ( + IN AML_OBJECT_NODE * BufferNode, + IN OUT AML_STREAM * FStream + ) +{ + EFI_STATUS Status; + AML_NODE_HEADER * NewNode; + CONST UINT8 * Buffer; + UINT32 BufferSize; + + // Check whether the node is an Object Node and has byte list. + if (!AmlNodeHasAttribute (BufferNode, AML_HAS_BYTE_LIST) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The buffer contains a list of resource data elements. + if (AmlRdIsResourceDataBuffer (FStream)) { + // Parse the resource data elements and add them as data nodes. + // AmlParseResourceData() moves the stream forward. + Status =3D AmlParseResourceData (BufferNode, FStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } else { + // The buffer doesn't contain a list of resource data elements. + // Create a single node holding the whole buffer data. + + // CreateDataNode checks the Buffer and BufferSize values. + Buffer =3D (CONST UINT8*)AmlStreamGetCurrPos (FStream); + BufferSize =3D AmlStreamGetFreeSpace (FStream); + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeRaw, + Buffer, + BufferSize, + (AML_DATA_NODE**)&NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlVarListAddTailInternal ( + (AML_NODE_HEADER*)BufferNode, + NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree (NewNode); + return Status; + } + + DumpRaw (Buffer, BufferSize); + + // Move the stream forward as we have consumed the Buffer. + Status =3D AmlStreamProgress (FStream, BufferSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } + + return Status; +} + +/** Parse the list of fixed arguments of the input ObjectNode. + + For each argument, create a node and add it to the fixed argument list + of the Node. + If a fixed argument has children, parse them. + + @param [in] ObjectNode Object node to parse the fixed arguments + from. + @param [in] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseFixedArguments ( + IN AML_OBJECT_NODE * ObjectNode, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * FixedArgNode; + AML_STREAM FixedArgFStream; + + EAML_PARSE_INDEX TermIndex; + EAML_PARSE_INDEX MaxIndex; + CONST AML_PARSE_FORMAT * Format; + + // Fixed arguments of method invocations node are handled differently. + if (!IS_AML_OBJECT_NODE (ObjectNode) || + AmlNodeCompareOpCode (ObjectNode, AML_METHOD_INVOC_OP, 0) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + TermIndex =3D EAmlParseIndexTerm0; + MaxIndex =3D (EAML_PARSE_INDEX)AmlGetFixedArgumentCount ( + (AML_OBJECT_NODE*)ObjectNode + ); + if ((ObjectNode->AmlByteEncoding !=3D NULL) && + (ObjectNode->AmlByteEncoding->Format !=3D NULL)) { + Format =3D ObjectNode->AmlByteEncoding->Format; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse all the FixedArgs. + while ((TermIndex < MaxIndex) && + !IS_END_OF_STREAM (FStream) && + (Format[TermIndex] !=3D EAmlNone)) { + // Initialize a FixedArgStream to parse the current fixed argument. + Status =3D AmlStreamInitSubStream (FStream, &FixedArgFStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Parse the current fixed argument. + Status =3D AmlParseArgument ( + (CONST AML_NODE_HEADER*)ObjectNode, + Format[TermIndex], + &FixedArgFStream, + NameSpaceRefList, + &FixedArgNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the fixed argument to the parent node's fixed argument list. + // FixedArgNode can be an object or data node. + Status =3D AmlSetFixedArgument ( + (AML_OBJECT_NODE*)ObjectNode, + TermIndex, + FixedArgNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + // Delete the sub-tree if the insertion failed. + // Otherwise its reference will be lost. + // Use DeleteTree because if the argument was a method invocation, + // multiple nodes have been created. + AmlDeleteTree (FixedArgNode); + return Status; + } + + // Parse the AML bytecode of the FixedArgNode if this is an object nod= e. + if (IS_AML_OBJECT_NODE (FixedArgNode) && + !IS_END_OF_STREAM (&FixedArgFStream)) { + Status =3D AmlParseStream ( + FixedArgNode, + &FixedArgFStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // Move the stream forward as we have consumed the sub-stream. + Status =3D AmlStreamProgress ( + FStream, + AmlStreamGetIndex (&FixedArgFStream) + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + TermIndex++; + } // while + + return EFI_SUCCESS; +} + +/** Parse the variable list of arguments of the input ObjectNode. + + For each variable argument, create a node and add it to the variable lis= t of + arguments of the Node. + If a variable argument has children, parse them recursively. + + The arguments of method invocation nodes are added to the variable list = of + arguments of the method invocation node. It is necessary to first get + the number of arguments to parse for this kind of node. A method invocat= ion + can have at most 7 fixed arguments. + + @param [in] Node Node to parse the variable arguments + from. + @param [in] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseVariableArguments ( + IN AML_NODE_HEADER * Node, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + BOOLEAN IsMethodInvocation; + UINT8 MethodInvocationArgCount; + + AML_NODE_HEADER * VarArgNode; + AML_STREAM VarArgFStream; + + if ((!AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_HAS_CHILD_OBJ + ) && + !IS_AML_ROOT_NODE (Node)) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlGetMethodInvocationArgCount ( + (CONST AML_OBJECT_NODE*)Node, + &IsMethodInvocation, + &MethodInvocationArgCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Parse variable arguments while the Stream is not empty. + while (!IS_END_OF_STREAM (FStream)) { + // If the number of variable arguments are counted, decrement the coun= ter. + if ((IsMethodInvocation) && (MethodInvocationArgCount-- =3D=3D 0)) { + return EFI_SUCCESS; + } + + // Initialize a VarArgStream to parse the current variable argument. + Status =3D AmlStreamInitSubStream (FStream, &VarArgFStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Parse the current variable argument. + Status =3D AmlParseArgument ( + Node, + EAmlObject, + &VarArgFStream, + NameSpaceRefList, + &VarArgNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the variable argument to its parent variable list of arguments. + // VarArgNode can be an object or data node. + Status =3D AmlVarListAddTailInternal ( + (AML_NODE_HEADER*)Node, + VarArgNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + // Delete the sub-tree if the insertion failed. + // Otherwise its reference will be lost. + // Use DeleteTree because if the argument was a method invocation, + // multiple nodes have been created. + AmlDeleteTree (VarArgNode); + return Status; + } + + // Parse the AML bytecode of the VarArgNode if this is an object node. + if (IS_AML_OBJECT_NODE (VarArgNode) && + (!IS_END_OF_STREAM (&VarArgFStream))) { + Status =3D AmlParseStream (VarArgNode, &VarArgFStream, NameSpaceRefL= ist); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // Move the stream forward as we have consumed the sub-stream. + Status =3D AmlStreamProgress ( + FStream, + AmlStreamGetIndex (&VarArgFStream) + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // while + + // If the number of variable arguments are counted, check all the + // MethodInvocationArgCount have been parsed. + if (IsMethodInvocation && (MethodInvocationArgCount !=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** Parse the AML stream and populate the root node. + + @param [in] RootNode RootNode to which the children are + added. + @param [in, out] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlPopulateRootNode ( + IN AML_ROOT_NODE * RootNode, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + if (!IS_AML_ROOT_NODE (RootNode) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // A Root Node only has variable arguments. + Status =3D AmlParseVariableArguments ( + (AML_NODE_HEADER*)RootNode, + FStream, + NameSpaceRefList + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Parse the AML stream an populate the object node. + + @param [in] ObjectNode ObjectNode to which the children are + added. + @param [in, out] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlPopulateObjectNode ( + IN AML_OBJECT_NODE * ObjectNode, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + if (!IS_AML_OBJECT_NODE (ObjectNode) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D EFI_SUCCESS; + + // Don't parse the fixed arguments of method invocation nodes. + // The AML encoding for method invocations in the ACPI specification 6.3= is: + // MethodInvocation :=3D NameString TermArgList + // Since the AML specification does not define an OpCode for method + // invocation, this AML parser defines a pseudo opcode and redefines the + // grammar for simplicity as: + // MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount Ter= mArgList + // ArgumentCount :=3D ByteData + // Due to this difference, the MethodInvocationOp and the fixed argument + // i.e. ArgumentCount is not available in the AML stream and need to be + // handled differently. + if (!AmlNodeCompareOpCode (ObjectNode, AML_METHOD_INVOC_OP, 0)) { + // Parse the fixed list of arguments. + Status =3D AmlParseFixedArguments ( + ObjectNode, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // Save the association [node reference/pathname] in the NameSpaceRefLis= t. + // This allows to identify method invocations from other namespace + // paths. Method invocation need to be parsed differently. + if (AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ObjectNode, + AML_IN_NAMESPACE)) { + Status =3D AmlAddNameSpaceReference ( + (CONST AML_OBJECT_NODE*)ObjectNode, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + if (!IS_END_OF_STREAM (FStream)) { + // Parse the variable list of arguments if present. + if (AmlNodeHasAttribute (ObjectNode, AML_HAS_CHILD_OBJ)) { + Status =3D AmlParseVariableArguments ( + (AML_NODE_HEADER*)ObjectNode, + FStream, + NameSpaceRefList + ); + } else if (AmlNodeHasAttribute (ObjectNode, AML_HAS_BYTE_LIST)) { + // Parse the byte list if present. + Status =3D AmlParseByteList ( + ObjectNode, + FStream + ); + } else if (AmlNodeHasAttribute (ObjectNode, AML_HAS_FIELD_LIST)) { + // Parse the field list if present. + Status =3D AmlParseFieldList ( + ObjectNode, + FStream, + NameSpaceRefList + ); + } + + // Check status and assert + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } + + return Status; +} + +/** Invoke the appropriate parsing functions based on the Node type. + + @param [in] Node Node from which the children are par= sed. + Must be a root node or an object nod= e. + @param [in] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlParseStream ( + IN AML_NODE_HEADER * Node, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + if (IS_AML_ROOT_NODE (Node)) { + Status =3D AmlPopulateRootNode ( + (AML_ROOT_NODE*)Node, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + } else if (IS_AML_OBJECT_NODE (Node)) { + Status =3D AmlPopulateObjectNode ( + (AML_OBJECT_NODE*)Node, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + } else { + // Data node or other. + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** Parse the definition block. + + This function parses the whole AML blob. It starts with the ACPI DSDT/SS= DT + header and then parses the AML bytestream. + A tree structure is returned via the RootPtr. + The tree must be deleted with the AmlDeleteTree function. + + @param [in] DefinitionBlock Pointer to the definition block. + @param [out] RootPtr Pointer to the root node of the tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseDefinitionBlock ( + IN CONST EFI_ACPI_DESCRIPTION_HEADER * DefinitionBlock, + OUT AML_ROOT_NODE ** RootPtr + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + AML_STREAM Stream; + AML_ROOT_NODE * Root; + + LIST_ENTRY NameSpaceRefList; + + UINT8 * Buffer; + UINT32 MaxBufferSize; + + if ((DefinitionBlock =3D=3D NULL) || + (RootPtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer =3D (UINT8*)DefinitionBlock + sizeof (EFI_ACPI_DESCRIPTION_HEADER= ); + if (DefinitionBlock->Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + MaxBufferSize =3D DefinitionBlock->Length - + (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER); + + // Create a root node. + Status =3D AmlCreateRootNode ( + (EFI_ACPI_DESCRIPTION_HEADER*)DefinitionBlock, + &Root + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + *RootPtr =3D Root; + + if (MaxBufferSize =3D=3D 0) { + return EFI_SUCCESS; + } + + // Initialize a stream to parse the AML bytecode. + Status =3D AmlStreamInit ( + &Stream, + Buffer, + MaxBufferSize, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Initialize the NameSpaceRefList, holding references to nodes declaring + // a name in the AML namespace. + InitializeListHead (&NameSpaceRefList); + + // Parse the whole AML blob. + Status =3D AmlParseStream ( + (AML_NODE_HEADER*)Root, + &Stream, + &NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Check the whole AML blob has been parsed. + if (!IS_END_OF_STREAM (&Stream)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto error_handler; + } + + // Print the list of NameSpace reference nodes. + // AmlDbgPrintNameSpaceRefList (&NameSpaceRefList); + + // Delete the NameSpaceRefList + goto exit_handler; + +error_handler: + if (Root !=3D NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)Root); + } + +exit_handler: + Status1 =3D AmlDeleteNameSpaceRefList (&NameSpaceRefList); + if (EFI_ERROR (Status1)) { + ASSERT (0); + if (!EFI_ERROR (Status)) { + return Status1; + } + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h b/Dy= namicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h new file mode 100644 index 0000000000000000000000000000000000000000..096a9596e161848bf5786f87a73= 6946aee69d4e3 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h @@ -0,0 +1,72 @@ +/** @file + AML Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_PARSER_H_ +#define AML_PARSER_H_ + +#include +#include + +/** Parse the list of fixed arguments of the input ObjectNode. + + For each argument, create a node and add it to the fixed argument list + of the Node. + If a fixed argument has children, parse them. + + @param [in] ObjectNode Object node to parse the fixed arguments + from. + @param [in] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseFixedArguments ( + IN AML_OBJECT_NODE * ObjectNode, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ); + +/** Parse the variable list of arguments of the input ObjectNode. + + For each variable argument, create a node and add it to the variable lis= t of + arguments of the Node. + If a variable argument has children, parse them recursively. + + The arguments of method invocation nodes are added to the variable list = of + arguments of the method invocation node. It is necessary to first get + the number of arguments to parse for this kind of node. A method invocat= ion + can have at most 7 fixed arguments. + + @param [in] Node Node to parse the variable arguments + from. + @param [in] FStream Forward stream containing the AML + bytecode to parse. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseVariableArguments ( + IN AML_NODE_HEADER * Node, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ); + +#endif // AML_PARSER_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64095): https://edk2.groups.io/g/devel/message/64095 Mute This Topic: https://groups.io/mt/76149174/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64094+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245828160652.8893316457443; Wed, 12 Aug 2020 08:23:48 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id LQvvYY1788612xf2rPXSpVLv; Wed, 12 Aug 2020 08:23:47 -0700 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com (EUR04-VI1-obe.outbound.protection.outlook.com [40.107.8.82]) by mx.groups.io with SMTP id smtpd.web11.17180.1597245821902606672 for ; Wed, 12 Aug 2020 08:23:42 -0700 X-Received: from DB6P191CA0023.EURP191.PROD.OUTLOOK.COM (2603:10a6:6:28::33) by AM5PR0801MB1841.eurprd08.prod.outlook.com (2603:10a6:203:2e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:28:cafe::2c) by DB6P191CA0023.outlook.office365.com (2603:10a6:6:28::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64094+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB5EUR03FT064.mail.protection.outlook.com (10.152.21.199) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:39 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 02d58a94a28e5e68 X-CR-MTA-TID: 64aa7808 X-Received: from fffea78f42a8.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 3EA1AB9E-3604-4CCB-A2FA-18812E5049B1.1; Wed, 12 Aug 2020 15:23:33 +0000 X-Received: from EUR03-DB5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id fffea78f42a8.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:33 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oF2H1dFAq6IZuptB2pKFN841uLfUtuzzkQRDN+N8wdMI1NycgwviTXP3Z0rVWZrZ1hQCLgfVQt974uomnuUhBo1+KBvCn8yz2l2qRuOjde/89nokFZMeWO8rTzTElffz2jHRkoFfqzcmihRORZsPrNn6NO2OyV7OqaQsyJvuQ00mKuRgWNwJXKYrti+smnyugDc8mU530WrBGxP8WAgw3/fzn3ZDfaf7/fTTNuqa7TsF65WBO39ifpsOIV25YXaTJGJCbTT8X5ROA4vu59Jch/KalJriMwEebj9FGK5lp4gasyYJlBo48s+H4PdMGh9Z9tqw1oMDUSSa2sJvovTPhQ== 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-SenderADCheck; bh=odB2sZkl1WjsS9WuezyqAWEpxUrPMRB1OI4b3qHuvUk=; b=JtPmM/YVk1yzL9fNF1w4dJh1FiRSPK3wHgMq+5S9bFf8dvLoUEY53LB4Kb5cSgLtptYv4pe4SpH3ZOxJ6rSj0h7rrPc9zVl/odO9TU/t2Nfmgj7ewggjXextXYYgcMJBRiWXMWcKmM0i9fzQLVHl5a2OjtPDr6aq44QUnjgwsUjdjvMBVyDUqkdKc7/vKsr+4h/j7Hr/ycf4s+X5wxDc9ibVjZovyaShEHcxmHC4TsC98TVXXWCKc6HdymTW/h5TmMpp2eCuatGxs34fzPwaQ1N5HVZ5jWnSgfOVXxTIW3oxIzabIscHsDJtTHDkKQnUkHUfTrr2/EwKESd+nXkdew== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0106.eurprd07.prod.outlook.com (2603:10a6:6:2c::20) by AM6PR08MB5144.eurprd08.prod.outlook.com (2603:10a6:20b:ec::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:32 +0000 X-Received: from DB5EUR03FT022.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2c:cafe::78) by DB6PR07CA0106.outlook.office365.com (2603:10a6:6:2c::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.10 via Frontend Transport; Wed, 12 Aug 2020 15:23:32 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT022.mail.protection.outlook.com (10.152.20.171) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:30 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:30 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 17/30] DynamicTablesPkg: AML resource data helper Date: Wed, 12 Aug 2020 16:22:23 +0100 Message-ID: <20200812152236.31164-18-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0b16986d-fb4e-4b1e-11be-08d83ed3b060 X-MS-TrafficTypeDiagnostic: AM6PR08MB5144:|AM5PR0801MB1841: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:5797;OLM:5797; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: olANRNyH0YHpkRtzWImg+ZbCWV5nYq04ZZtQcF3QEhvppLFFRKyF+4bdQQoeHT5s89J6SZiWM0XF5g+YuLhIbcj7u/jgOHQNQ5DoR8IcmRbEh/9DRU8NUXEUk8ROmnusFPDu5GnWtUkeesQmQZL2b9HuBkOt88yC+vAqMwdi4Qninwp48mQHgZ0QrrBi93T+E+aTPknzQ4iO3bJes4xIk2LYxZw2a1Udf5dtIvdONP49UuPueBO5Xr5ipoLpYtUbFS8wmFzDiX8ollTic8ySFPQh9M4RE5ZQHpR2Sfxemrkv/ImX8q1VgwwvRakod5Ho3QMpxUYvRY4J75Xv4iU+Fcoe40No9lRR3Qytm9sBKtq9g8VdFDRuEsNAxOlNKYuqdICMK5A8V//5QWtn/wG9kw== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(136003)(376002)(346002)(39860400002)(396003)(46966005)(6916009)(186003)(6666004)(86362001)(4326008)(1076003)(8676002)(8936002)(54906003)(336012)(7696005)(316002)(26005)(478600001)(83380400001)(44832011)(47076004)(2906002)(36756003)(82740400003)(81166007)(70586007)(70206006)(356005)(82310400002)(2616005)(5660300002)(426003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB5144 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 86b55e45-081b-4b51-36a5-08d83ed3ac1a X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:39.0902 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0b16986d-fb4e-4b1e-11be-08d83ed3b060 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: DB5EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1841 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 5YFoa6LR82wJLSHAhrJhXGaCx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245827; bh=KBQEbPrZIPaX44FNDEFEjx5OlQFUjRzrjWHWyxo7F8E=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=FvU18/AQZ9W49H5xsNwXcpWGFyVhiTU/8Q0buHbA+/flHMn2bIM7ysAQjBiBFy0i341 l8z6vdIz+19ZrIdTRO14gi0i6XwQJlgdU8KJytX1ViwwYJK7fmdHf3qgUQxTSXsHH24sa a7SiCPLqzr9SCYBJzFbcbsILz7oXG6KiuA4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Resource data are defined in the ACPI 6.3 specification, s6.4 "Resource Data Types for ACPI". They can be created using the ASL ResourceTemplate () statement, cf s19.3.3 "ASL Resource Templates". Resource data can be of the small or large type and are defined by their encoding. The resource data is stored in the Bytelist of a BufferOp node. To simplify operations on resource data, the resource data parser examines the Bytelist to detect the presence of resource data. If the data matches the encoding of resource data type(s), the parser fragments the resource data buffer into resource data elements (data nodes) and stores them in the variable arguments list of the BufferOp node. The resource data helper provides functions and macros to assist operations on resource data elements. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c | 10= 3 ++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h | 17= 4 ++++++++++++++++++++ 2 files changed, 277 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourc= eData.c b/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceDa= ta.c new file mode 100644 index 0000000000000000000000000000000000000000..8b46c7232df3bb7d49e5faa1362= a485a6a413198 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c @@ -0,0 +1,103 @@ +/** @file + AML Resource Data. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rd or RD - Resource Data + - Rds or RDS - Resource Data Small + - Rdl or RDL - Resource Data Large +**/ + +#include + +/** Check whether the resource data has the input descriptor Id. + + The small/large bit is included in the descriptor Id, + but the size bits are not included for small resource data elements. + + @param [in] Header Pointer to the first byte of a resource data + element. + @param [in] DescriptorId The descriptor to check against. + + @retval TRUE The resource data has the descriptor Id. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlRdCompareDescId ( + IN CONST AML_RD_HEADER * Header, + IN AML_RD_HEADER DescriptorId + ) +{ + if (Header =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + if (AML_RD_IS_LARGE (Header)) { + return ((*Header ^ DescriptorId) =3D=3D 0); + } else { + return (((*Header & AML_RD_SMALL_ID_MASK) ^ DescriptorId) =3D=3D 0); + } +} + +/** Get the descriptor Id of the resource data. + + The small/large bit is included in the descriptor Id, + but the size bits are not included for small resource data elements. + + @param [in] Header Pointer to the first byte of a resource data. + + @return A descriptor Id. +**/ +AML_RD_HEADER +EFIAPI +AmlRdGetDescId ( + IN CONST AML_RD_HEADER * Header + ) +{ + if (Header =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + if (AML_RD_IS_LARGE (Header)) { + return *Header; + } + + // Header is a small resource data element. + return *Header & AML_RD_SMALL_ID_MASK; +} + +/** Get the size of a resource data element. + + If the resource data element is of the large type, the Header + is expected to be at least 3 bytes long. + + @param [in] Header Pointer to the first byte of a resource data. + + @return The size of the resource data element. +**/ +UINT32 +EFIAPI +AmlRdGetSize ( + IN CONST AML_RD_HEADER * Header + ) +{ + if (Header =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + if (AML_RD_IS_LARGE (Header)) { + return ((ACPI_LARGE_RESOURCE_HEADER*)Header)->Length + + sizeof (ACPI_LARGE_RESOURCE_HEADER); + } + + // Header is a small resource data element. + return ((ACPI_SMALL_RESOURCE_HEADER*)Header)->Bits.Length + + sizeof (ACPI_SMALL_RESOURCE_HEADER); +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourc= eData.h b/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceDa= ta.h new file mode 100644 index 0000000000000000000000000000000000000000..48e4e2aaddb47e3847cb896e9bc= 64d4c68bda9f4 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h @@ -0,0 +1,174 @@ +/** @file + AML Resource Data. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rd or RD - Resource Data + - Rds or RDS - Resource Data Small + - Rdl or RDL - Resource Data Large +**/ + +#ifndef AML_RESOURCE_DATA_H_ +#define AML_RESOURCE_DATA_H_ + +/* This header file does not include internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions + must be included by the caller file. The function prototypes must + only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node + definitions. + This allows to keep the functions defined here both internal and + potentially external. If necessary, any function of this file can + be exposed externally. + The Api folder is internal to the AmlLib, but should only use these + functions. They provide a "safe" way to interact with the AmlLib. +*/ + +#include +#include + +/** + @defgroup ResourceDataLibrary Resource data library + @ingroup AMLLib + @{ + Resource data are defined in the ACPI 6.3 specification, + s6.4 "Resource Data Types for ACPI". They can be created in ASL via the + ResourceTemplate () statement, cf s19.3.3 "ASL Resource Templates". + + Resource data can be of the small or large type. The difference between + small and large resource data elements is their encoding. + + Resource data are stored in the variable list of arguments of object + nodes. + @} +*/ + +/** Resource Descriptor header for Small/Large Resource Data Object. + This is the first byte of a Small/Large Resource Data element. + + Can be a ACPI_SMALL_RESOURCE_HEADER or ACPI_LARGE_RESOURCE_HEADER. + + @ingroup ResourceDataStructures +*/ +typedef UINT8 AML_RD_HEADER; + +/** Mask for the small resource data size. + + @ingroup ResourceDataStructures +*/ +#define AML_RD_SMALL_SIZE_MASK (0x7U) + +/** Mask for the small resource data ID. + + @ingroup ResourceDataStructures +*/ +#define AML_RD_SMALL_ID_MASK (0xFU << 3) + +/** Mask for the large resource data ID. + + @ingroup ResourceDataStructures +*/ +#define AML_RD_LARGE_ID_MASK (0x7FU) + +/** + @defgroup ResourceDataApis Resource data APIs + @ingroup ResourceDataLibrary + @{ + Resource data APIs allow to manipulate/decode resource data elements. + @} +*/ + +/** Check whether a resource data is of the large type. + + @ingroup ResourceDataApis + + @param [in] Header Pointer to the first byte of a resource data. + + @retval TRUE If the resource data is of the large type. + @retval FALSE Otherwise. +**/ +#define AML_RD_IS_LARGE(Header) = \ + (((ACPI_SMALL_RESOURCE_HEADER*)Header)->Bits.Type =3D=3D = \ + ACPI_LARGE_ITEM_FLAG) + +/** Build a small resource data descriptor Id. + The small/large bit is included in the descriptor Id, + but the size bits are not included. + + @ingroup ResourceDataApis + + @param [in] Id Descriptor Id. + + @return A descriptor Id. +**/ +#define AML_RD_BUILD_SMALL_DESC_ID(Id) ((AML_RD_HEADER)((Id & 0xF) << 3)) + +/** Build a large resource data descriptor Id. + The small/large bit is included in the descriptor Id. + + @ingroup ResourceDataApis + + @param [in] Id Id of the descriptor. + + @return A descriptor Id. +**/ +#define AML_RD_BUILD_LARGE_DESC_ID(Id) ((AML_RD_HEADER)((BIT7) | Id)) + +/** Check whether the resource data has the input descriptor Id. + + The small/large bit is included in the descriptor Id, + but the size bits are not included for small resource data elements. + + @ingroup ResourceDataApis + + @param [in] Header Pointer to the first byte of a resource data + element. + @param [in] DescriptorId The descriptor to check against. + + @retval TRUE The resource data has the descriptor Id. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlRdCompareDescId ( + IN CONST AML_RD_HEADER * Header, + IN AML_RD_HEADER DescriptorId + ); + +/** Get the descriptor Id of the resource data. + + The small/large bit is included in the descriptor Id, + but the size bits are not included for small resource data elements. + + @ingroup ResourceDataApis + + @param [in] Header Pointer to the first byte of a resource data. + + @return A descriptor Id. +**/ +AML_RD_HEADER +EFIAPI +AmlRdGetDescId ( + IN CONST AML_RD_HEADER * Header + ); + +/** Get the size of a resource data element. + + If the resource data element is of the large type, the Header + is expected to be at least 3 bytes long. + + @ingroup ResourceDataApis + + @param [in] Header Pointer to the first byte of a resource data. + + @return The size of the resource data element. +**/ +UINT32 +EFIAPI +AmlRdGetSize ( + IN CONST AML_RD_HEADER * Header + ); + +#endif // AML_RESOURCE_DATA_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64094): https://edk2.groups.io/g/devel/message/64094 Mute This Topic: https://groups.io/mt/76149170/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64096+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245832693733.9095057535983; Wed, 12 Aug 2020 08:23:52 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5M61YY1788612xQ1sEsJM8d9; Wed, 12 Aug 2020 08:23:52 -0700 X-Received: from EUR04-HE1-obe.outbound.protection.outlook.com (EUR04-HE1-obe.outbound.protection.outlook.com [40.107.7.70]) by mx.groups.io with SMTP id smtpd.web11.17182.1597245823557543539 for ; Wed, 12 Aug 2020 08:23:44 -0700 X-Received: from DB6PR1001CA0043.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:4:55::29) by AM6PR08MB3414.eurprd08.prod.outlook.com (2603:10a6:20b:49::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:40 +0000 X-Received: from DB5EUR03FT033.eop-EUR03.prod.protection.outlook.com (2603:10a6:4:55:cafe::dc) by DB6PR1001CA0043.outlook.office365.com (2603:10a6:4:55::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:40 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64096+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB5EUR03FT033.mail.protection.outlook.com (10.152.20.76) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:40 +0000 X-Received: ("Tessian outbound e8cdb8c6f386:v64"); Wed, 12 Aug 2020 15:23:40 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 6f2841092e1bd280 X-CR-MTA-TID: 64aa7808 X-Received: from 15c0b06b166d.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 6CE33DF1-2F36-415A-AC85-BAD67601E3DD.1; Wed, 12 Aug 2020 15:23:34 +0000 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 15c0b06b166d.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:34 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bgBf+ylXXazaH4xBDk/PF6k3WtC/pNIPqT0NQcB6QJIctBp2kNyBXXo+IlsU0js+Fbln1Kvjg8DJDbTcivgu3jzXVKgeNa+6WX5rlxc0mylbZ7KLIhbQKvsA9/gFQJpx8wzJOfgFMllR5kExjYEAuRIp1MyXTyi0pRb+kKpo4LDJZN0z4XENKcT4/CDOS8WZdOFFWsMjOYuVdie42TmLRcQOsblvdjzeo60ON713F0PYuQTHmK8ymDI754/Fd1J05Z+v9EHKyn+JE/0xls4Jh9ysUU1s+KWDPzQhQUZJHX5y2ZXyGsrPIidDRcfPGfmgi2aq0rCIqhEkXXEhNShiGw== 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-SenderADCheck; bh=VtprhbB1p11RhDJQCctur0BJYBOvLPtCmJpU8dA8eJs=; b=YxeeeWo9tUD7yM8QKc2DBLx9TpgSOookCiKXVXLu6vBptEJ2eba2AFMUBxgYNV3sVvRG3G1s0RO0EtY59qQaiu/kEHT+Div6QEX2dBgwjaB7qYIUjTce/a3UY2PMJkMYUFSXIQPEfOSeIvAPnV+1tybZIDxN29Gd0wUMxGmWzvoIHouU0mcGnisvPT02EDNfEhu1o8TlgpAfW3C3rp7Z2Y3Uv99yDJBCBdyaKurx88AGov1qC7QV+NkxFzKl3SbhVqyPlXdk1vLhscBlmNqn1RcvxL2yLxbWUfwZOl3djCGNqsY7rfP+HPS+tuNXd60FmFDmvfqUS7EMWoNxmIO7vg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6PR08CA0008.eurprd08.prod.outlook.com (2603:10a6:20b:b2::20) by AM6PR08MB4231.eurprd08.prod.outlook.com (2603:10a6:20b:73::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.15; Wed, 12 Aug 2020 15:23:33 +0000 X-Received: from AM5EUR03FT017.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:b2:cafe::4b) by AM6PR08CA0008.outlook.office365.com (2603:10a6:20b:b2::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:33 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT017.mail.protection.outlook.com (10.152.16.89) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:32 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:32 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:31 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:31 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 18/30] DynamicTablesPkg: AML resource data parser Date: Wed, 12 Aug 2020 16:22:24 +0100 Message-ID: <20200812152236.31164-19-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: b03bfa16-d3b0-46a9-7eeb-08d83ed3b0f9 X-MS-TrafficTypeDiagnostic: AM6PR08MB4231:|AM6PR08MB3414: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4502;OLM:4502; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: 3qEbDLDHkencp51N0fxXw//rwhQuckp+ZXgy7eZBJpGALF1behD8ryllbWw9aiR0YkaZTds/2g+43fTdutEZBuIc4yCD9vX6Z4G3hrzT/EI3fMSDm+PHvGk1pIVjo/EtYu7rsAOs64Nwpbx48ZsbgptRB4Et3+7vUmhKfxwVar3UU4Gpo34mMh7fz9jNkKv9137ZkDIwawm+vtcvS/I0UO/vDECGCpGt2knSdUHxc9s63asje6e06bWdUrPyJeyVb7FtU00LRHNqQIA27E21HRmYTYjThbBK0DgdzauzrCt8unEPjMlhrDsbVEMB9o9/SuvQt9XzazJiThMQsRI4Qo5+d43LPU+Lq4P2TuJbmFqcMs9G/38BOX50dQEZXpS3T15/mpXOIh9+4XdEHz3j9A== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(136003)(376002)(39860400002)(346002)(396003)(46966005)(316002)(82740400003)(478600001)(8676002)(356005)(83380400001)(8936002)(70586007)(54906003)(30864003)(81166007)(47076004)(70206006)(7696005)(336012)(82310400002)(5660300002)(186003)(6666004)(86362001)(26005)(2906002)(44832011)(6916009)(36756003)(4326008)(426003)(1076003)(2616005);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB4231 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT033.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 284b9630-8f50-46d9-c0a0-08d83ed3acb4 X-Microsoft-Antispam-Message-Info: PeTB+gw0Qb4uw5ZXUYFIGpHfcwwMswAE/WHReID2NlYXpghNl6099M9MV7eTnmPIIbnHUoNRiB3XAI6150dKXZjW0d23dxnNUgtZqaLRudPyhL2trVK2eyMMA4ehPqaSTJGfReZC141nsJpX8T10qlm8XI7RRe83X650XCwM+KZN7TcV7rPeCv3gSX4yQZYy/9RlN4/TngnX0z+6RhFTeVsjr/pPTtuV4zviPxsjGrFPALo81qVRFVJBDjchejxHE608trBLw42pYiBAhh77R/sWisneU/0AY7jUWbr2gb2wYmrcOGf+kBKDGRCm4QzE3yXoJh8JtJAj7IspqOWGyjgoiS6t7OdZmeOIVQ2NTrcRXJT8rDI8Eo9pBmkhgyCRJo7DkE1bIu2PvDiLs2TzxQ== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:40.1007 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b03bfa16-d3b0-46a9-7eeb-08d83ed3b0f9 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: DB5EUR03FT033.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3414 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: H8Cl0TY3SkL1OAu4yC8IIZo7x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245832; bh=TSOOstj2sCroqu2ym9WI6700GjsmH9rQdHpjuju6W2I=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=vX+yvCcowQzyq2KSbUcJ3ZgLkYmrMAOZDXNvezSlZAhB0tgY4hfQ6XMkaKQL3TRMSWL A7YDqqY/Kb4LIEVdYqssMS+Z1n1gxH3cQYxXVPA4fUl/0XTRLWJNvTycp7ZcxI3JOTldq rFCNBr9qa7Lp+heEDi9shAODWpdQtcSR2n0= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Resource data are defined in the ACPI 6.3 specification, s6.4 "Resource Data Types for ACPI". They can be created using the ASL ResourceTemplate () statement, cf s19.3.3 "ASL Resource Templates". Resource data can be of the small or large type and are defined by their encoding. The resource data is stored in the Bytelist of a BufferOp node. The Bytelist of a BufferOp node is represented by an AML Data node in the AML tree. The resource data parser, examines the Bytelist (Data node buffer) to detect the presence of resource data. If the Bytelist data matches the encoding for resource data types, the resource data parser fragments the Bytelist containing the resource data buffer into resource data elements represented as individual Data nodes and stores them in the variable arguments list of the BufferOp object nodes. Example: ASL code and the corresponding AML tree representation for the resource data. ASL Code Reviewed-by: Alexei Fedorov -------- Name (_CRS, ResourceTemplate() { QWordMemory (...) Interrupt (...) } AML Tree -------- (NameOp) \ |-[_CRS]-[BufferOp] # Fixed Arguments |-{NULL} \ # Variable Argument \ list |-[BuffSize] # Fixed Arguments |-{(Rd1)->(Rd2)->(EndTag)} # Variable Argument list Where: Rd1 - QWordMemory resource data element. Rd2 - Interrupt resource data element. EndTag - Resource data end tag. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar --- DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c | 32= 8 ++++++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h | 7= 1 +++++ 2 files changed, 399 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataP= arser.c b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataPars= er.c new file mode 100644 index 0000000000000000000000000000000000000000..09fb3e72586c3f31ce6d90f049e= 77a041330ba18 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c @@ -0,0 +1,328 @@ +/** @file + AML Resource Data Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rd or RD - Resource Data + - Rds or RDS - Resource Data Small + - Rdl or RDL - Resource Data Large +**/ + +#include + +#include +#include +#include +#include + +/** Get the size of a resource data element using a stream. + + If the resource data element is of the large type, the Header + is expected to be at least 3 bytes long. + + The use of a stream makes this function safer + than the version without stream. + + @param [in] FStream Forward stream pointing to a resource data + element. + The stream must not be at its end. + + @return The size of the resource data element. + Zero if error. +**/ +UINT32 +EFIAPI +AmlRdStreamGetRdSize ( + IN CONST AML_STREAM * FStream + ) +{ + CONST AML_RD_HEADER * CurrRdElement; + + if (!IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream)) { + ASSERT (0); + return 0; + } + + CurrRdElement =3D (CONST AML_RD_HEADER*)AmlStreamGetCurrPos (FStream); + if (CurrRdElement =3D=3D NULL) { + ASSERT (0); + return 0; + } + + // If the resource data element is of the large type, check for overflow. + if (AML_RD_IS_LARGE (CurrRdElement) && + (AmlStreamGetFreeSpace (FStream) < + sizeof (ACPI_LARGE_RESOURCE_HEADER))) { + return 0; + } + + return AmlRdGetSize (CurrRdElement); +} + +/** Check the nesting of resource data elements that are dependent + function descriptors. + + @param [in] FStream Forward stream pointing to a resource = data + element. The stream is not + modified/progressing. + The stream must not be at its end. + @param [in, out] InFunctionDesc Pointer holding the nesting of the + resource data buffer. + InFunctionDesc holds TRUE if the resou= rce + data at the address of Buffer is curre= ntly + in a dependent function descriptor lis= t. + + @retval FALSE The Header being parsed is ending a function descriptor + list when none started. This should not be possible for a + resource data buffer. + @retval TRUE Otherwise. +**/ +STATIC +BOOLEAN +EFIAPI +AmlRdCheckFunctionDescNesting ( + IN CONST AML_STREAM * FStream, + IN OUT BOOLEAN * InFunctionDesc + ) +{ + CONST AML_RD_HEADER * CurrRdElement; + + if (!IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + (InFunctionDesc =3D=3D NULL)) { + ASSERT (0); + return FALSE; + } + + CurrRdElement =3D AmlStreamGetCurrPos (FStream); + if (CurrRdElement =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + // Starting a dependent function descriptor. + // It is possible to start one when one has already started. + if (AmlRdCompareDescId ( + CurrRdElement, + AML_RD_BUILD_SMALL_DESC_ID ( + ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME))) { + *InFunctionDesc =3D TRUE; + return TRUE; + } + + // Ending a dependent function descriptor. + if (AmlRdCompareDescId ( + CurrRdElement, + AML_RD_BUILD_SMALL_DESC_ID ( + ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME))) { + if (*InFunctionDesc) { + *InFunctionDesc =3D FALSE; + return TRUE; + } + + // It should not be possible to end a dependent function descriptor + // when none started. + return FALSE; + } + + return TRUE; +} + +/** Check whether the input stream is pointing to a valid list + of resource data elements. + + The check is based on the size of resource data elements. + This means that a buffer can pass this check with non-existing descripto= r Ids + that have a correct size. + + A list of resource data elements can contain one unique resource data + element, without an end tag resource data. This is the case for + a FieldList. + + @param [in] FStream Forward stream ideally pointing to a resource + data element. The stream is not + modified/progressing. + The stream must not be at its end. + + @retval TRUE The buffer is holding a valid list of resource data elem= ents. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlRdIsResourceDataBuffer ( + IN CONST AML_STREAM * FStream + ) +{ + EFI_STATUS Status; + UINT32 FreeSpace; + AML_STREAM SubStream; + CONST AML_RD_HEADER * CurrRdElement; + UINT32 CurrRdElementSize; + BOOLEAN InFunctionDesc; + + if (!IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream)) { + ASSERT (0); + return FALSE; + } + + // Create a sub-stream from the input stream to leave it untouched. + Status =3D AmlStreamInitSubStream (FStream, &SubStream); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + CurrRdElement =3D AmlStreamGetCurrPos (&SubStream); + if (CurrRdElement =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + // The first element cannot be an end tag. + if (AmlRdCompareDescId ( + CurrRdElement, + AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) { + return FALSE; + } + + InFunctionDesc =3D FALSE; + while (TRUE) { + FreeSpace =3D AmlStreamGetFreeSpace (&SubStream); + CurrRdElement =3D AmlStreamGetCurrPos (&SubStream); + CurrRdElementSize =3D AmlRdStreamGetRdSize (&SubStream); + if ((FreeSpace =3D=3D 0) || + (CurrRdElement =3D=3D NULL) || + (CurrRdElementSize =3D=3D 0)) { + return FALSE; + } + + if (!AmlRdCheckFunctionDescNesting (&SubStream, &InFunctionDesc)) { + return FALSE; + } + + if (CurrRdElementSize > FreeSpace) { + return FALSE; + } else if (CurrRdElementSize =3D=3D FreeSpace) { + return TRUE; + } + + // TODO Might want to check the CRC when available. + // An end tag resource data element must be the last element of the li= st. + // Thus the function should have already returned. + if (AmlRdCompareDescId ( + CurrRdElement, + AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))= ) { + return FALSE; + } + + Status =3D AmlStreamProgress (&SubStream, CurrRdElementSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + } // while + + return FALSE; +} + +/** Parse a ResourceDataBuffer. + + For each resource data element, create a data node + and add them to the variable list of arguments of the BufferNode. + + The input stream is expected to point to a valid list of resource data + elements. A function is available to check it for the caller. + + @param [in] BufferNode Buffer node. + @param [in] FStream Forward stream pointing to a resource data + element. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseResourceData ( + IN AML_OBJECT_NODE * BufferNode, + IN AML_STREAM * FStream + ) +{ + EFI_STATUS Status; + AML_DATA_NODE * NewNode; + UINT32 FreeSpace; + CONST AML_RD_HEADER * CurrRdElement; + UINT32 CurrRdElementSize; + + // Check that BufferNode is an ObjectNode and has a ByteList. + if (!AmlNodeHasAttribute (BufferNode, AML_HAS_BYTE_LIST) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Iterate through the resource data elements and create nodes. + // We assume the Buffer has already been validated as a list of + // resource data elements, so less checks are made. + while (TRUE) { + FreeSpace =3D AmlStreamGetFreeSpace (FStream); + if (FreeSpace =3D=3D 0) { + break; + } + + CurrRdElement =3D (CONST AML_RD_HEADER*)AmlStreamGetCurrPos (FStream); + CurrRdElementSize =3D AmlRdStreamGetRdSize (FStream); + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeResourceData, + (CONST UINT8*)CurrRdElement, + CurrRdElementSize, + &NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlVarListAddTailInternal ( + (AML_NODE_HEADER*)BufferNode, + (AML_NODE_HEADER*)NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)NewNode); + return Status; + } + + Status =3D AmlStreamProgress (FStream, CurrRdElementSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + DumpRaw (CurrRdElement, CurrRdElementSize); + + // Exit the loop when finding the resource data end tag. + if (AmlRdCompareDescId ( + CurrRdElement, + AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))= ) { + if (FreeSpace !=3D CurrRdElementSize) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + break; + } + } // while + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataP= arser.h b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataPars= er.h new file mode 100644 index 0000000000000000000000000000000000000000..13dfb352c416ff2be86d28dc502= 0529c9442fa2a --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h @@ -0,0 +1,71 @@ +/** @file + AML Resource Data Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rd or RD - Resource Data + - Rds or RDS - Resource Data Small + - Rdl or RDL - Resource Data Large +**/ + +#ifndef AML_RESOURCE_DATA_PARSER_H_ +#define AML_RESOURCE_DATA_PARSER_H_ + +#include +#include +#include + +/** Check whether the input stream is pointing to a valid list + of resource data elements. + + The check is based on the size of resource data elements. + This means that a buffer can pass this check with non-existing descripto= r Ids + that have a correct size. + + A list of resource data elements can contain one unique resource data + element, without an end tag resource data. This is the case for + a FieldList. + + @param [in] FStream Forward stream ideally pointing to a resource + data element. The stream is not + modified/progressing. + The stream must not be at its end. + + @retval TRUE The buffer is holding a valid list of resource data elem= ents. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlRdIsResourceDataBuffer ( + IN CONST AML_STREAM * FStream + ); + +/** Parse a ResourceDataBuffer. + + For each resource data element, create a data node + and add them to the variable list of arguments of the BufferNode. + + The input stream is expected to point to a valid list of resource data + elements. A function is available to check it for the caller. + + @param [in] BufferNode Buffer node. + @param [in] FStream Forward stream pointing to a resource data + element. + The stream must not be at its end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseResourceData ( + IN AML_OBJECT_NODE * BufferNode, + IN AML_STREAM * FStream + ); + +#endif // AML_RESOURCE_DATA_PARSER_H_ + --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64096): https://edk2.groups.io/g/devel/message/64096 Mute This Topic: https://groups.io/mt/76149175/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64098+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245839849834.4823228310967; Wed, 12 Aug 2020 08:23:59 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id apFKYY1788612xHzvVsBhVyf; Wed, 12 Aug 2020 08:23:59 -0700 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com (EUR05-DB8-obe.outbound.protection.outlook.com [40.107.20.85]) by mx.groups.io with SMTP id smtpd.web10.17203.1597245829210537875 for ; Wed, 12 Aug 2020 08:23:49 -0700 X-Received: from AM6PR10CA0089.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::30) by DB8PR08MB5370.eurprd08.prod.outlook.com (2603:10a6:10:112::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:46 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::9a) by AM6PR10CA0089.outlook.office365.com (2603:10a6:209:8c::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:46 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64098+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:46 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:45 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 16c901cf8e9e4b4a X-CR-MTA-TID: 64aa7808 X-Received: from 9d1fdebe1f73.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id B7FA1F68-4F19-4540-90C4-0323998DBCDB.1; Wed, 12 Aug 2020 15:23:40 +0000 X-Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 9d1fdebe1f73.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:40 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Gx89gIOl2MJ8SSomRrR9WRF7QpXDeWV76HyVGKF1qAA0duDZ/0Dczetz9Ikj2brt+1S+Ob8ltWW6xstE9EaQfQVudV+TC9AT3TqTvvD/putt6vN7/y/m3Qw/MV1WL6zgg7yxXEL1BHuu7aW+ahSVvy9y+tWXk6xSkNIsSBDUROaL0HftabhNwk+MFLzUWzkAvBvH2aDNq/7w+TljWSI/h1L8jaiAVx1/M9RPuz1Nlwd66qqTY8Ox/OB950N774g73D8VUlnQanjdX8TkvE5dJpR0xbUMAZ6fXbMMOztPNsKKswmcOOLdLTyRm2oO9D2dxvoHMFa5lOlPlHCKtLVO+g== 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-SenderADCheck; bh=hRA6T0jL1uWdHz1YsSa6+FladEe9XKtdr80k7A/Bwwc=; b=PBCg0nHODQCeott3CxpbfbHCmij449qla+Q9NZpwzNn4DA35/OVnuwSNa6QDX0ii2wczaHMhoK+In3uacea0URg2GRmIJ/PZMqqXrpVYbKYIpxENtMfHNBkvnOYYTKwIJGjsRrJGcMJaC2fVPXH39fM408hfQhdB9Mc2w/qWnCMFdySB0x+2m0Lo8bpSF+1eo7VTe7rvJuLTQrtihBCQkJvchvgg6yg5sOO2XBf6RQhF4G2Bg375tm9GoHPayGmN6C+7e65CwifbVOMrKNkvGoEA0WYA4f+eSJsXsok9ugdG93IyDIGNbFFWeL7WCuls25t7MR4S+bAM9fd7TCBk5g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0050.eurprd07.prod.outlook.com (2603:10a6:6:2a::12) by AM6PR08MB4472.eurprd08.prod.outlook.com (2603:10a6:20b:bf::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::90) by DB6PR07CA0050.outlook.office365.com (2603:10a6:6:2a::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.8 via Frontend Transport; Wed, 12 Aug 2020 15:23:37 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:32 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:32 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 19/30] DynamicTablesPkg: AML Method parser Date: Wed, 12 Aug 2020 16:22:25 +0100 Message-ID: <20200812152236.31164-20-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 85c927be-2e39-4421-658a-08d83ed3b488 X-MS-TrafficTypeDiagnostic: AM6PR08MB4472:|DB8PR08MB5370: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:9508;OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: 2TFjhn/UyZiuVOhKTwMunIUCBiIuKshMn9tdpKpPkGvM5Agun0DNnYRAxJe0HBK4IssmyIzsvdXdAiBAW9vR16C9NrjIcIgugr41HrZjr9UM7HqoTn0t3xQaTwJzm1FKKwqmEYk+LPRVA3WlrnIGuMSVVqBobb7b1gSIv2mmYz9xBrVzvHbxTPMAKMYYwHrM/0FROARRjqztRDy+8J8XbQVzheSQKga9peF39aM2h+rMv0lmd0VQ6YEhBZltGPkmiQaxAjbm/31Gvig0dxNc0DpDBaYQiFjSEZXLW6PcSFq+XAc923rWoli5XKO8Rx7XTu5mChGL09SndOY/TpLbNfYOXYZeeOTbK9Y/TTgxXAD9Sv8WCgeU26R0+B8pLgM/2HRGV2UEzVafVFJx09bc2A== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(376002)(39860400002)(346002)(396003)(136003)(46966005)(1076003)(6916009)(5660300002)(82740400003)(82310400002)(6666004)(4326008)(7696005)(356005)(186003)(478600001)(30864003)(83380400001)(47076004)(81166007)(426003)(19627235002)(8676002)(8936002)(70586007)(36756003)(2616005)(2906002)(316002)(70206006)(54906003)(336012)(86362001)(44832011)(26005)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB4472 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 32c19ced-a910-495f-cd2d-08d83ed3af9b X-Microsoft-Antispam-Message-Info: jNKugpdziB1SIsoF0HPAHdPDe1q/VpatYlSGAQnQ0oy/CKQLteR+WI52YNylKsUr9R0CmWBgrXIvGLsBuFNU3ZCNRTu/s8r8ppUGHtB42bcUk01+ngkbBluYYu0sS5pteVmaO5w2ceEymv7KVab+xVBIq+S2tashBht8ATqLgDGRb4z0KncuhEW9YrK+q7kwKBnFyFtr1ks5nL2DM55JM9Xb7toZL9WoOErya0tnH96nTi2EkAirI01XOcLgw2VBBMpIvG2cFXASdqJJ82fkscl2bBVkcAXVNEiVZcWZwnMnulJzDPOa3Yfk1TtHsBChjxJG4cKRuNIfLkciCpBLnl9/kpByX18rbh5UsNc01VdobrC7n47//0lL4occSlWZUuN6+jiUf+uJqf1xVhxhUg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:46.0014 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 85c927be-2e39-4421-658a-08d83ed3b488 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: AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB5370 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: UBXq0jNOJrqz2WsX4dpfn7VMx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245839; bh=qKBJMS7+2N7ehJVSX70gfrAaHi0vesI5JbL/9vz9mKw=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=i1VxHl5jDujbVaMXQ73mez4vCKMPOgsK+a6qKNZCUCf/5YL6Rdw3HWzCT66AxiQybCA rMXus/gqG7lyMoj4OBV4rtzoHsd2fK33h5y0K9spIeAWkk0P3BlKHIIMofc04mBpqQmgn aSyZNzblEo4jdaVJkOcstwUbsW1VeVuZH4s= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML language allows a Definition Block to implement methods that an Operating System can invoke at runtime. Although Dynamic AML does not provide interfaces to modify AML methods; an AML template code may contain methods and/or method invocations. Method definitions have an opcode defined in the AML encoding and can be easily parsed. However, the language does not define an opcode for method invocation. Method invocations are represented as a NameString followed by the arguments to the method. This poses a significant challenge for the AML parser as it has to determine if a NameString appearing in the AML byte stream is a method invocation and if it is a method invocation, then how many arguments follow. This also means the Method definition must occur prior to the method invocation in the AML byte stream. This is a hard requirement for the AML parser. The AML method parser maintains a NameSpaceRefList that keeps a track of every namespace node and its raw AML absolute path. The AmlIsMethodInvocation() searches the NameSpaceRefList to determine if a NameString matches a Method definition. A pseudo opcode has been defined in the AML encoding to represent the Method invocation in the AML tree. The AML encoding for method invocations in the ACPI specification 6.3 is: MethodInvocation :=3D NameString TermArgList The AmlLib library redefines this as: MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount TermArgList ArgumentCount :=3D ByteData Where MethodInvocationOp is the pseudo opcode and ArgumentCount is the number of arguments passed to the method. NOTE: The AmlLib library's definition for a method invocation only applies to the representation of method invocation node in the AML tree. When computing the size of a tree or serialising it, the additional data is not taken into account i.e. the MethodInvocationOp and the ArgumentCount are stripped before serialising. Method invocation nodes have the AML_METHOD_INVOVATION attribute set in the AmlLib library's representation of the AML encoding. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c | 1458 +++= +++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h | 188 +++ 2 files changed, 1646 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.= c b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c new file mode 100644 index 0000000000000000000000000000000000000000..bc98d950b579dec3243dab355a7= 11a56dca978ea --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c @@ -0,0 +1,1458 @@ +/** @file + AML Method Parser. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/** Delete a namespace reference node and its pathname. + + It is the caller's responsibility to check the NameSpaceRefNode has been + removed from any list the node is part of. + + @param [in] NameSpaceRefNode Pointer to an AML_NAMESPACE_REF_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlDeleteNameSpaceRefNode ( + IN AML_NAMESPACE_REF_NODE * NameSpaceRefNode + ) +{ + if (NameSpaceRefNode =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (NameSpaceRefNode->RawAbsolutePath !=3D NULL) { + FreePool ((CHAR8*)NameSpaceRefNode->RawAbsolutePath); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (NameSpaceRefNode); + return EFI_SUCCESS; +} + +/** Delete a list of namespace reference nodes. + + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteNameSpaceRefList ( + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + LIST_ENTRY * CurrentLink; + + if (NameSpaceRefList =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + while (!IsListEmpty (NameSpaceRefList)) { + CurrentLink =3D NameSpaceRefList->ForwardLink; + RemoveEntryList (CurrentLink); + Status =3D AmlDeleteNameSpaceRefNode ( + (AML_NAMESPACE_REF_NODE*)CurrentLink + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // while + + return EFI_SUCCESS; +} + +/** Create an AML_NAMESPACE_REF_NODE. + + A Buffer is allocated to store the raw AML absolute path. + + @param [in] ObjectNode Node being part of the namespace. + Must be have the AML_IN_NAMESPACE + attribute. + @param [in] RawAbsolutePath AML raw absolute path of the ObjectNod= e. + A raw NameString is a concatenated list + of 4 chars long names. + @param [in] RawAbsolutePathSize Size of the RawAbsolutePath buffer. + @param [out] NameSpaceRefNodePtr The created AML_METHOD_REF_NODE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCreateMethodRefNode ( + IN CONST AML_OBJECT_NODE * ObjectNode, + IN CONST CHAR8 * RawAbsolutePath, + IN UINT32 RawAbsolutePathSize, + OUT AML_NAMESPACE_REF_NODE ** NameSpaceRefNodePtr + ) +{ + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) || + (RawAbsolutePath =3D=3D NULL) || + (RawAbsolutePathSize =3D=3D 0) || + (NameSpaceRefNodePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + NameSpaceRefNode =3D AllocateZeroPool (sizeof (AML_NAMESPACE_REF_NODE)); + if (NameSpaceRefNode =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + NameSpaceRefNode->RawAbsolutePathSize =3D RawAbsolutePathSize; + NameSpaceRefNode->RawAbsolutePath =3D AllocateCopyPool ( + RawAbsolutePathSize, + RawAbsolutePath + ); + if (NameSpaceRefNode->RawAbsolutePath =3D=3D NULL) { + FreePool (NameSpaceRefNode); + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (&NameSpaceRefNode->Link); + + NameSpaceRefNode->NodeRef =3D ObjectNode; + *NameSpaceRefNodePtr =3D NameSpaceRefNode; + + return EFI_SUCCESS; +} + +#if !defined (MDEPKG_NDEBUG) + +/** Print the list of raw absolute paths of the NameSpace reference list. + + @param [in] NameSpaceRefList List of NameSpace reference nodes. +**/ +VOID +EFIAPI +AmlDbgPrintNameSpaceRefList ( + IN CONST LIST_ENTRY * NameSpaceRefList + ) +{ + LIST_ENTRY * CurrLink; + AML_NAMESPACE_REF_NODE * CurrNameSpaceNode; + + if (NameSpaceRefList =3D=3D NULL) { + ASSERT (0); + return; + } + + DEBUG ((DEBUG_INFO, "AmlMethodParser: List of available raw AML paths:\n= ")); + + CurrLink =3D NameSpaceRefList->ForwardLink; + while (CurrLink !=3D NameSpaceRefList) { + CurrNameSpaceNode =3D (AML_NAMESPACE_REF_NODE*)CurrLink; + + AmlDbgPrintChars ( + DEBUG_INFO, + CurrNameSpaceNode->RawAbsolutePath, + CurrNameSpaceNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_INFO, "\n")); + + CurrLink =3D CurrLink->ForwardLink; + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +#endif // MDEPKG_NDEBUG + +/** From a forward stream pointing to a NameString, + initialize a raw backward stream. + + StartOfStream + Fstream: CurrPos EndOfStream + v v + +-----------------------------------------+ + |^^^[Multi-name prefix]AAAA.BBBB.CCCC | + +-----------------------------------------+ + ^ ^ + RawPathNameBStream: EndOfStream CurrPos + StartOfStream + + No memory is allocated when initializing the stream. + + @param [in] FStream Forward stream pointing to a NameStrin= g. + The stream must not be at its end. + @param [out] RawPathNameBStream Backward stream containing the + raw AML path. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlInitRawPathBStream ( + IN CONST AML_STREAM * FStream, + OUT AML_STREAM * RawPathNameBStream + ) +{ + EFI_STATUS Status; + + UINT8 * RawPathBuffer; + CONST CHAR8 * Buffer; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if (!IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (RawPathNameBStream =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Buffer =3D (CONST CHAR8*)AmlStreamGetCurrPos (FStream); + if (Buffer =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the NameString information. + Status =3D AmlParseNameStringInfo ( + Buffer, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the beginning of the raw NameString. + RawPathBuffer =3D (UINT8*)AmlGetFirstNameSeg ( + Buffer, + Root, + ParentPrefix + ); + if (RawPathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Initialize a backward stream containing the raw path. + Status =3D AmlStreamInit ( + RawPathNameBStream, + RawPathBuffer, + (SegCount * AML_NAME_SEG_SIZE), + EAmlStreamDirectionBackward + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Get the first node in the ParentNode branch that is part of the + AML namespace and has its name defined. + + This is different from getting the first namespace node. This function is + necessary because an absolute path is built while the tree is not comple= te + yet. The parsing is ongoing. + + For instance, the ASL statement "CreateXXXField ()" adds a field in the + AML namespace, but the name it defines is the last fixed argument of the + corresponding object. + If an AML path is referenced in its first fixed argument, it is not + possible to resolve the name of the CreateXXXField object. However, the = AML + path is not part of the scope created by the CreateXXXField object, so t= his + scope can be skipped. + + In the following ASL code, the method invocation to MET0 is done in the + "CreateField" statement. The "CreateField" statement defines the "FIEL" + path in the AML namespace. However, MET0 must be not be resolved in the + "CreateField" object scope. It needs to be resolved in its parent. + ASL code: + Method (MET0, 0,,, BuffObj) { + Return (Buffer (0x1000) {}) + } + CreateField (MET0(), 0x100, 0x4, FIEL) + + @param [in] Node Node to get the first named node from, in + its hierarchy. + @param [out] OutNamedNode First named node in Node's hierarchy. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlGetFirstNamedAncestorNode ( + IN CONST AML_NODE_HEADER * Node, + OUT AML_NODE_HEADER ** OutNamedNode + ) +{ + EFI_STATUS Status; + CONST AML_NODE_HEADER * NameSpaceNode; + + if ((!IS_AML_OBJECT_NODE (Node) && + !IS_AML_ROOT_NODE (Node)) || + (OutNamedNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // If Node is not the root node and doesn't have a name defined yet, + // get the ancestor NameSpace node. + while (!IS_AML_ROOT_NODE (Node) && + !(AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)Node, + AML_IN_NAMESPACE) && + AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node) !=3D NULL)) { + Status =3D AmlGetFirstAncestorNameSpaceNode ( + Node, + (AML_NODE_HEADER**)&NameSpaceNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + // The NameSpaceNode may not have its name defined as yet. In this + // case get the next ancestor node. + Node =3D NameSpaceNode; + } + + *OutNamedNode =3D (AML_NODE_HEADER*)Node; + + return EFI_SUCCESS; +} + +/** From a ParentNode and a forward stream pointing to a relative path, + build a raw AML absolute path and return it in a backward stream. + + No memory is allocated in this function, the out stream must be initiali= zed + with a buffer long enough to hold any raw absolute AML path. + + @param [in] ParentNode Parent node of the namespace + node from which the absolute + path is built. ParentNode isn't + necessarily a namespace node. + Must be a root or an object no= de. + @param [in] PathnameFStream Forward stream pointing to the + beginning of a pathname (any + NameString). + The stream must not be at its = end. + @param [in, out] AbsolutePathBStream Backward stream where the raw + absolute path is written. The + stream must be already initial= ized. + The stream must not be at its = end. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlBuildRawMethodAbsolutePath ( + IN CONST AML_NODE_HEADER * ParentNode, + IN CONST AML_STREAM * PathnameFStream, + IN OUT AML_STREAM * AbsolutePathBStream + ) +{ + EFI_STATUS Status; + + AML_NODE_HEADER * NamedParentNode; + UINT8 * RawPathBuffer; + CONST CHAR8 * CurrPos; + + UINT32 Root; + UINT32 ParentPrefix; + UINT32 SegCount; + + if ((!IS_AML_OBJECT_NODE (ParentNode) && + !IS_AML_ROOT_NODE (ParentNode)) || + !IS_STREAM (PathnameFStream) || + IS_END_OF_STREAM (PathnameFStream) || + !IS_STREAM_FORWARD (PathnameFStream) || + !IS_STREAM (AbsolutePathBStream) || + IS_END_OF_STREAM (AbsolutePathBStream) || + !IS_STREAM_BACKWARD (AbsolutePathBStream)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CurrPos =3D (CONST CHAR8*)AmlStreamGetCurrPos (PathnameFStream); + if (CurrPos =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the NameString information. + Status =3D AmlParseNameStringInfo ( + CurrPos, + &Root, + &ParentPrefix, + &SegCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Copy the method invocation raw relative path at the end of the Stream. + if (SegCount !=3D 0) { + // Get the beginning of the raw NameString. + RawPathBuffer =3D (UINT8*)AmlGetFirstNameSeg ( + CurrPos, + Root, + ParentPrefix + ); + + Status =3D AmlStreamWrite ( + AbsolutePathBStream, + RawPathBuffer, + SegCount * AML_NAME_SEG_SIZE + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // If the pathname contained an absolute path, this is finished, return. + if (Root) { + return Status; + } + + // Get the first named node of the parent node in its hierarchy. + Status =3D AmlGetFirstNamedAncestorNode (ParentNode, &NamedParentNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Build the raw absolute path of the namespace node. + Status =3D AmlGetRawNameSpacePath ( + NamedParentNode, + ParentPrefix, + AbsolutePathBStream + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Compare two raw NameStrings stored in forward streams. + Compare them NameSeg by NameSeg (a NameSeg is 4 bytes long). + + The two raw NameStrings can be of different size. + + @param [in] RawFStream1 First forward stream to compare. + Points to the beginning of the raw NameStr= ing. + @param [in] RawFStream2 Second forward stream to compare. + Points to the beginning of the raw NameStr= ing. + @param [out] CompareCount Count of identic bytes. + Must be a multiple of 4 (size of a NameSeg= ). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCompareRawNameString ( + IN CONST AML_STREAM * RawFStream1, + IN CONST AML_STREAM * RawFStream2, + OUT UINT32 * CompareCount + ) +{ + EFI_STATUS Status; + UINT32 Index; + + AML_STREAM RawFStream1Clone; + AML_STREAM RawFStream2Clone; + UINT32 Stream1Size; + UINT32 Stream2Size; + UINT32 CompareLen; + + // Raw NameStrings have a size that is a multiple of the size of NameSeg= s. + if (!IS_STREAM (RawFStream1) || + IS_END_OF_STREAM (RawFStream1) || + !IS_STREAM_FORWARD (RawFStream1) || + !IS_STREAM (RawFStream2) || + IS_END_OF_STREAM (RawFStream2) || + (CompareCount =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream1Size =3D AmlStreamGetFreeSpace (RawFStream1); + if ((Stream1Size & (AML_NAME_SEG_SIZE - 1)) !=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Stream2Size =3D AmlStreamGetFreeSpace (RawFStream2); + if ((Stream2Size & (AML_NAME_SEG_SIZE - 1)) !=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlStreamClone (RawFStream1, &RawFStream1Clone); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlStreamClone (RawFStream2, &RawFStream2Clone); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + CompareLen =3D MIN (Stream1Size, Stream2Size); + Index =3D 0; + // Check there is enough space for a NameSeg in both Stream1 and Stream2. + while (Index < CompareLen) { + if (!AmlStreamCmp ( + &RawFStream1Clone, + &RawFStream2Clone, + AML_NAME_SEG_SIZE) + ) { + // NameSegs are different. Break. + break; + } + + Status =3D AmlStreamProgress (&RawFStream1Clone, AML_NAME_SEG_SIZE); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + Status =3D AmlStreamProgress (&RawFStream2Clone, AML_NAME_SEG_SIZE); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Index +=3D AML_NAME_SEG_SIZE; + } + + *CompareCount =3D Index; + + return EFI_SUCCESS; +} + +/** Check whether an alias can be resolved to a method definition. + + Indeed, the following ASL code must be handled: + Method (MET0, 1) { + Return (0x9) + } + Alias (\MET0, \ALI0) + Alias (\ALI0, \ALI1) + \ALI1(0x5) + When searching for \ALI1 in the AML NameSpace, it resolves to \ALI0. + When searching for \ALI0 in the AML NameSpace, it resolves to \MET0. + When searching for \MET0 in the AML NameSpace, it resolves to a method + definition. + + This method is a wrapper to recursively call AmlFindMethodDefinition. + + @param [in] AliasNode Pointer to an Alias object node. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If success, and if the alias is reso= lved + to a method definition (this can go + through other alias indirections), + containing the corresponding + NameSpaceRef node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlResolveAliasMethod ( + IN CONST AML_OBJECT_NODE * AliasNode, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + AML_STREAM SourceAliasFStream; + CONST AML_DATA_NODE * DataNode; + + if (!AmlNodeCompareOpCode (AliasNode, AML_ALIAS_OP, 0) || + (NameSpaceRefList =3D=3D NULL) || + (OutNameSpaceRefNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The aliased NameString (the source name) is the first fixed argument, + // cf. ACPI6.3 spec, s19.6.4: Alias (SourceObject, AliasObject) + DataNode =3D (CONST AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)AliasNode, + EAmlParseIndexTerm0 + ); + if (DataNode =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Initialize a stream on the source alias NameString. + Status =3D AmlStreamInit ( + &SourceAliasFStream, + DataNode->Buffer, + DataNode->Size, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Recursively check whether the source alias NameString + // is a method invocation. + Status =3D AmlIsMethodInvocation ( + AmlGetParent ((AML_NODE_HEADER*)AliasNode), + &SourceAliasFStream, + NameSpaceRefList, + OutNameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + return Status; +} + +/** Iterate through the MethodList to find the best namespace resolution. + If the pathname resolves to a method definition, returns it. + + For instance, if the AML namespace is: + \ + \-MET0 <- Device definition, absolute path: \MET0 + \-AAAA + \-MET0 <- Method definition, absolute path: \AAAA.MET0 + \-MET1 <- Method definition, absolute path: \AAAA.MET1 + \-BBBB + \-CCCC + \-DDDD + \-MET0 <- Method definition, absolute path: \AAAA.BBBB.CCCC.DDDD= .MET0 + + The list of the available pathnames is: + [NameSpaceRefList] + - \MET0 <- Device definition + - \AAAA + - \AAAA.MET0 <- Method definition + - \AAAA.MET1 <- Method definition + - \AAAA.BBBB + - \AAAA.BBBB.CCCC + - \AAAA.BBBB.CCCC.DDDD + - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition + + Depending on where the method invocation is done, the method definition + referenced changes. If the method call "MET0" is done from + \AAAA.BBBB.CCCC: + 1. Identify which pathnames end with "MET0": + - \MET0 <- Device definition + - \AAAA.MET0 <- Method definition + - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition + 2. Resolve the method invocation: + - \AAAA.MET0 <- Method definition + 3. \AAAA.MET0 is a method definition, so return the corresponding + reference node. + + @param [in] RawAbsolutePathFStream Forward stream pointing to a raw + absolute path. + The stream must not be at its en= d. + @param [in] RawPathNameBStream Backward stream pointing to a raw + pathname. This raw pathname is t= he + raw NameString of namespace node. + The stream must not be at its en= d. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If the two input paths are + referencing a method definition, + returns the corresponding + NameSpaceRef node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlFindMethodDefinition ( + IN CONST AML_STREAM * RawAbsolutePathFStream, + IN CONST AML_STREAM * RawPathNameBStream, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + + LIST_ENTRY * NextLink; + + // To resolve a pathname, scope levels need to be compared. + UINT32 NameSegScopeCount; + UINT32 PathNameSegScopeCount; + UINT32 ProbedScopeCount; + UINT32 BestScopeCount; + + AML_STREAM ProbedRawAbsoluteFStream; + AML_STREAM ProbedRawAbsoluteBStream; + + AML_NAMESPACE_REF_NODE * ProbedNameSpaceRefNode; + AML_NAMESPACE_REF_NODE * BestNameSpaceRefNode; + + if (!IS_STREAM (RawAbsolutePathFStream) || + IS_END_OF_STREAM (RawAbsolutePathFStream) || + !IS_STREAM_FORWARD (RawAbsolutePathFStream) || + ((AmlStreamGetIndex (RawAbsolutePathFStream) & + (AML_NAME_SEG_SIZE - 1)) !=3D 0) = || + !IS_STREAM (RawPathNameBStream) || + IS_END_OF_STREAM (RawPathNameBStream) || + !IS_STREAM_BACKWARD (RawPathNameBStream) || + ((AmlStreamGetIndex (RawPathNameBStream) & + (AML_NAME_SEG_SIZE - 1)) !=3D 0) = || + (NameSpaceRefList =3D=3D NULL) = || + (OutNameSpaceRefNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Checking absolute name: ")); + AmlDbgPrintChars ( + DEBUG_VERBOSE, + (CONST CHAR8*)AmlStreamGetCurrPos (RawAbsolutePathFStream), + AmlStreamGetMaxBufferSize (RawAbsolutePathFStream) + ); + DEBUG ((DEBUG_VERBOSE, ".\n")); + + BestNameSpaceRefNode =3D NULL; + BestScopeCount =3D 0; + NameSegScopeCount =3D AmlStreamGetMaxBufferSize (RawAbsolutePathFStream); + PathNameSegScopeCount =3D AmlStreamGetMaxBufferSize (RawPathNameBStream); + + // Iterate through the raw AML absolute path to find the best match. + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Comparing with: ")); + NextLink =3D NameSpaceRefList->ForwardLink; + while (NextLink !=3D NameSpaceRefList) { + ProbedNameSpaceRefNode =3D (AML_NAMESPACE_REF_NODE*)NextLink; + + // Print the raw absolute path of the probed node. + AmlDbgPrintChars ( + DEBUG_VERBOSE, + ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_VERBOSE, "; ")); + + // If the raw AML absolute path of the probed node is longer than the + // searched pathname, continue. + // E.g.: The method call \MET0 cannot resolve to a method defined at + // \AAAA.MET0. The method definition is out of scope. + if (PathNameSegScopeCount > ProbedNameSpaceRefNode->RawAbsolutePathSiz= e) { + NextLink =3D NextLink->ForwardLink; + continue; + } + + // Initialize a backward stream for the probed node. + // This stream is used to compare the ending of the pathnames. + // E.g. if the method searched ends with "MET0", pathnames not ending = with + // "MET0" should be skipped. + Status =3D AmlStreamInit ( + &ProbedRawAbsoluteBStream, + (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Compare the pathname endings. If they don't match, continue. + if (!AmlStreamCmp ( + RawPathNameBStream, + &ProbedRawAbsoluteBStream, + AmlStreamGetMaxBufferSize (RawPathNameBStream))) { + NextLink =3D NextLink->ForwardLink; + continue; + } + + // Initialize a forward stream for the probed node. + // This stream is used to count how many scope levels from the root + // are common with the probed node. The more there are, the better it = is. + // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2 + // pathnames ending with MET0: + // - \AAAA.MET0 has 1 NameSeg in common with \AAAA.BBBB.MET0 + // from the root (this is "AAAA"); + // - \MET0 has 0 NameSeg in common with \AAAA.BBBB.MET0 + // from the root; + // Thus, the best match is \AAAA.MET0. + Status =3D AmlStreamInit ( + &ProbedRawAbsoluteFStream, + (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath, + ProbedNameSpaceRefNode->RawAbsolutePathSize, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Count how many namespace levels are in common from the root. + Status =3D AmlCompareRawNameString ( + RawAbsolutePathFStream, + &ProbedRawAbsoluteFStream, + &ProbedScopeCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (ProbedScopeCount =3D=3D NameSegScopeCount) { + // This is a perfect match. Exit the loop. + BestNameSpaceRefNode =3D ProbedNameSpaceRefNode; + break; + } else if (ProbedScopeCount > BestScopeCount) { + // The probed node has more scope levels in common than the + // last best match. Update the best match. + BestScopeCount =3D ProbedScopeCount; + BestNameSpaceRefNode =3D ProbedNameSpaceRefNode; + } else if (ProbedScopeCount =3D=3D BestScopeCount) { + // The probed node has the same number of scope levels in + // common as the last best match. + if (ProbedScopeCount =3D=3D 0) { + // There was not best match previously. Set it. + BestNameSpaceRefNode =3D ProbedNameSpaceRefNode; + } else { + // (ProbedScopeCount !=3D 0) + // If there is an equivalent candidate, the best has the shortest + // absolute path. Indeed, a similar ProbedScopeCount and a longer + // path means the definition is out of the scope. + // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2 + // pathnames ending with MET0: + // - \AAAA.MET0 has 1 NameSegs in common with \AAAA.BBBB.ME= T0 + // from the root (this is "AAAA"); + // - \AAAA.CCCC.MET0 has 1 NameSegs in common with + // \AAAA.BBBB.MET0 from the root (this is "AAAA"); + // As \AAAA.CCCC.MET0 is longer than \AAAA.MET0, it means th= at + // the pathname could have matched on more NameSegs, but it + // didn't because it is out of scope. + // Thus, the best match is \AAAA.MET0. + if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) < + BestNameSpaceRefNode->RawAbsolutePathSize) { + BestScopeCount =3D ProbedScopeCount; + BestNameSpaceRefNode =3D ProbedNameSpaceRefNode; + } else if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) =3D=3D + BestNameSpaceRefNode->RawAbsolutePathSize) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + } + + NextLink =3D NextLink->ForwardLink; + } + + DEBUG ((DEBUG_VERBOSE, "\n")); + + // Check whether the BestNameSpaceRefNode is a method definition. + if (BestNameSpaceRefNode !=3D NULL) { + if (AmlIsMethodDefinitionNode (BestNameSpaceRefNode->NodeRef)) { + *OutNameSpaceRefNode =3D BestNameSpaceRefNode; + } else if (AmlNodeCompareOpCode ( + BestNameSpaceRefNode->NodeRef, + AML_ALIAS_OP, 0)) { + // The path matches an alias. Resolve the alias and check whether + // this is a method defintion. + Status =3D AmlResolveAliasMethod ( + BestNameSpaceRefNode->NodeRef, + NameSpaceRefList, + OutNameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } else { + // If no, return NULL, even if a matching pathname has been found. + *OutNameSpaceRefNode =3D NULL; + } + + return EFI_SUCCESS; +} + +/** Check whether a pathname is a method invocation. + + If there is a matching method definition, returns the corresponding + NameSpaceRef node. + + To do so, the NameSpaceRefList is keeping track of every namespace node + and its raw AML absolute path. + To check whether a pathname is a method invocation, a corresponding raw + absolute pathname is built. This raw absolute pathname is then compared + to the list of available pathnames. If a pathname defining a method + matches the scope of the input pathname, return. + + @param [in] ParentNode Parent node. Node to which the node to= be + created will be attached. + @param [in] FStream Forward stream pointing to the NameStr= ing + to find. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If the NameString pointed by FStream is + a method invocation, OutNameSpaceRefNo= de + contains the NameSpaceRef corresponding + to the method definition. + NULL otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlIsMethodInvocation ( + IN CONST AML_NODE_HEADER * ParentNode, + IN CONST AML_STREAM * FStream, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ) +{ + EFI_STATUS Status; + + AML_STREAM RawPathNameBStream; + AML_STREAM RawAbsolutePathFStream; + + AML_STREAM RawAbsolutePathBStream; + UINT8 * RawAbsolutePathBuffer; + UINT32 RawAbsolutePathBufferSize; + + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + if ((!IS_AML_OBJECT_NODE (ParentNode) && + !IS_AML_ROOT_NODE (ParentNode)) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL) || + (OutNameSpaceRefNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // There cannot be a method invocation in a field list. Return. + if (AmlNodeHasAttribute ( + (CONST AML_OBJECT_NODE*)ParentNode, + AML_HAS_FIELD_LIST)) { + *OutNameSpaceRefNode =3D NULL; + return EFI_SUCCESS; + } + + // Allocate memory for the raw absolute path. + RawAbsolutePathBufferSize =3D MAX_AML_NAMESTRING_SIZE; + RawAbsolutePathBuffer =3D AllocateZeroPool (RawAbsolutePathBufferSize); + if (RawAbsolutePathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Initialize a backward stream to get the raw absolute path. + Status =3D AmlStreamInit ( + &RawAbsolutePathBStream, + RawAbsolutePathBuffer, + RawAbsolutePathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Build the raw AML absolute path of the namespace node. + Status =3D AmlBuildRawMethodAbsolutePath ( + ParentNode, + FStream, + &RawAbsolutePathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // If this is the root path: it cannot be a method invocation. Just retu= rn. + if (AmlStreamGetIndex (&RawAbsolutePathBStream) =3D=3D 0) { + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: " + "Root node cannot be a method invocation\n" + )); + *OutNameSpaceRefNode =3D NULL; + Status =3D EFI_SUCCESS; + goto exit_handler; + } + + // Create a forward stream for the raw absolute path. + // This forward stream only contains the raw absolute path with + // no extra free space. + Status =3D AmlStreamInit ( + &RawAbsolutePathFStream, + AmlStreamGetCurrPos (&RawAbsolutePathBStream), + AmlStreamGetIndex (&RawAbsolutePathBStream), + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Create a backward stream for the node name. + Status =3D AmlInitRawPathBStream ( + FStream, + &RawPathNameBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Go through the NameSpaceRefList elements to check for + // a corresponding method definition. + NameSpaceRefNode =3D NULL; + Status =3D AmlFindMethodDefinition ( + &RawAbsolutePathFStream, + &RawPathNameBStream, + NameSpaceRefList, + &NameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + +#if !defined(MDEPKG_NDEBUG) + // Print whether a method definition has been found. + if (NameSpaceRefNode !=3D NULL) { + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: Corresponding method definition: " + )); + AmlDbgPrintChars ( + DEBUG_VERBOSE, + NameSpaceRefNode->RawAbsolutePath, + NameSpaceRefNode->RawAbsolutePathSize + ); + DEBUG ((DEBUG_VERBOSE, ".\n")); + + } else { + DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: No method definition found.\n= ")); + } +#endif // MDEPKG_NDEBUG + + *OutNameSpaceRefNode =3D NameSpaceRefNode; + +exit_handler: + // Free allocated memory. + FreePool (RawAbsolutePathBuffer); + return Status; +} + +/** Create a namespace reference node and add it to the NameSpaceRefList. + + When a namespace node is encountered, the namespace it defines must be + associated to the node. This allow to keep track of the nature of each + name present in the AML namespace. + + In the end, this allows to recognize method invocations and parse the ri= ght + number of arguments after the method name. + + @param [in] Node Namespace node. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlAddNameSpaceReference ( + IN CONST AML_OBJECT_NODE * Node, + IN OUT LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + AML_NAMESPACE_REF_NODE * NameSpaceRefNode; + + AML_STREAM NodeNameFStream; + EAML_PARSE_INDEX NameIndex; + CONST AML_DATA_NODE * NameNode; + + AML_STREAM RawAbsolutePathBStream; + UINT32 RawAbsolutePathBStreamSize; + + CHAR8 * AbsolutePathBuffer; + UINT32 AbsolutePathBufferSize; + + CONST AML_NODE_HEADER * ParentNode; + + if (!AmlNodeHasAttribute (Node, AML_IN_NAMESPACE) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Allocate a buffer to get the raw AML absolute pathname of the + // namespace node. + AbsolutePathBufferSize =3D MAX_AML_NAMESTRING_SIZE; + AbsolutePathBuffer =3D AllocateZeroPool (AbsolutePathBufferSize); + if (AbsolutePathBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AmlStreamInit ( + &RawAbsolutePathBStream, + (UINT8*)AbsolutePathBuffer, + AbsolutePathBufferSize, + EAmlStreamDirectionBackward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Get the index where the name of the Node is stored in its + // fixed list of arguments. + Status =3D AmlNodeGetNameIndex (Node, &NameIndex); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Get the Node name. + NameNode =3D (CONST AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)Node, + NameIndex + ); + if (!IS_AML_DATA_NODE (NameNode) || + (NameNode->DataType !=3D EAmlNodeDataTypeNameString)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Initialize a stream on the node name of the namespace node. + // This is an AML NameString. + Status =3D AmlStreamInit ( + &NodeNameFStream, + NameNode->Buffer, + NameNode->Size, + EAmlStreamDirectionForward + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + ParentNode =3D AmlGetParent ((AML_NODE_HEADER*)Node); + if (ParentNode =3D=3D NULL) { + ASSERT (0); + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + // Build the raw AML absolute path of the namespace node. + Status =3D AmlBuildRawMethodAbsolutePath ( + ParentNode, + &NodeNameFStream, + &RawAbsolutePathBStream + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + RawAbsolutePathBStreamSize =3D AmlStreamGetIndex (&RawAbsolutePathBStrea= m); + // This is the root path: this cannot be a method invocation. + if (RawAbsolutePathBStreamSize =3D=3D 0) { + Status =3D EFI_SUCCESS; + goto exit_handler; + } + + // Create a NameSpace reference node. + Status =3D AmlCreateMethodRefNode ( + Node, + (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream), + RawAbsolutePathBStreamSize, + &NameSpaceRefNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Add the created NameSpaceRefNode to the list. + InsertTailList (NameSpaceRefList, &NameSpaceRefNode->Link); + + DEBUG (( + DEBUG_VERBOSE, + "AmlMethodParser: Adding namespace reference with name:\n" + )); + AmlDbgPrintChars ( + DEBUG_VERBOSE, + (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream), + AmlStreamGetIndex (&RawAbsolutePathBStream) + ); + DEBUG ((DEBUG_VERBOSE, "\n")); + +exit_handler: + // Free allocated memory. + FreePool (AbsolutePathBuffer); + + return Status; +} + +/** Create a method invocation node. + + The AML grammar does not attribute an OpCode/SubOpCode couple for + method invocations. This library is representing method invocations + as if they had one. + + The AML encoding for method invocations in the ACPI specification 6.3 is: + MethodInvocation :=3D NameString TermArgList + In this library, it is: + MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount Term= ArgList + ArgumentCount :=3D ByteData + + When computing the size of a tree or serializing it, the additional data= is + not taken into account (i.e. the MethodInvocationOp and the ArgumentCoun= t). + + Method invocation nodes have the AML_METHOD_INVOVATION attribute. + + @param [in] NameSpaceRefNode NameSpaceRef node pointing to the + the definition of the invoked + method. + @param [in] MethodInvocationName Data node containing the method + invocation name. + @param [out] MethodInvocationNodePtr Created method invocation node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateMethodInvocationNode ( + IN CONST AML_NAMESPACE_REF_NODE * NameSpaceRefNode, + IN AML_DATA_NODE * MethodInvocationName, + OUT AML_OBJECT_NODE ** MethodInvocationNodePtr + ) +{ + EFI_STATUS Status; + + UINT8 ArgCount; + AML_DATA_NODE * ArgCountNode; + AML_NODE_HEADER ** FixedArgs; + AML_OBJECT_NODE * MethodDefinitionNode; + AML_OBJECT_NODE * MethodInvocationNode; + + if ((NameSpaceRefNode =3D=3D NULL) = || + !AmlIsMethodDefinitionNode (NameSpaceRefNode->NodeRef) || + !IS_AML_DATA_NODE (MethodInvocationName) || + (MethodInvocationName->DataType !=3D EAmlNodeDataTypeNameString) || + (MethodInvocationNodePtr =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the number of arguments of the method. + MethodDefinitionNode =3D (AML_OBJECT_NODE*)NameSpaceRefNode->NodeRef; + FixedArgs =3D MethodDefinitionNode->FixedArgs; + // The method definition is an actual method definition. + if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_METHOD_OP, 0)) { + // Cf ACPI 6.3 specification: + // DefMethod :=3D MethodOp PkgLength NameString MethodFlags TermList + // MethodOp :=3D 0x14 + // MethodFlags :=3D ByteData bit 0-2: ArgCount (0-7) + // bit 3: SerializeFlag + // 0 NotSerialized + // 1 Serialized + // bit 4-7: SyncLevel (0x00-0x0f) + + // Read the MethodFlags to decode the ArgCount. + ArgCountNode =3D (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm1]; + ArgCount =3D *((UINT8*)ArgCountNode->Buffer) & 0x7; + } else if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_EXTERNAL_OP, = 0)) { + // The method definition is an external statement. + // Cf ACPI 6.3 specification: + // DefExternal :=3D ExternalOp NameString ObjectType ArgumentCount + // ExternalOp :=3D 0x15 + // ObjectType :=3D ByteData + // ArgumentCount :=3D ByteData (0 =E2=80=93 7) + + // Read the ArgumentCount. + ArgCountNode =3D (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm2]; + ArgCount =3D *((UINT8*)ArgCountNode->Buffer); + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Create the object node for the method invocation. + // MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount + // MethodInvocationOp :=3D Pseudo Opcode for Method Invocation + // NameString :=3D Method Name + // ArgumentCount :=3D ByteData (0 =E2=80=93 7) + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_METHOD_INVOC_OP, 0), + 0, + &MethodInvocationNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // The first fixed argument is the method name. + Status =3D AmlSetFixedArgument ( + MethodInvocationNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)MethodInvocationName + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Create a data node holding the number of arguments + // of the method invocation. + ArgCountNode =3D NULL; + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeUInt, + &ArgCount, + sizeof (UINT8), + &ArgCountNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // The second fixed argument is the number of arguments. + Status =3D AmlSetFixedArgument ( + MethodInvocationNode, + EAmlParseIndexTerm1, + (AML_NODE_HEADER*)ArgCountNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + *MethodInvocationNodePtr =3D MethodInvocationNode; + return Status; + +error_handler: + // Delete the sub-tree: the method invocation name is already attached. + AmlDeleteTree ((AML_NODE_HEADER*)MethodInvocationNode); + if (ArgCountNode !=3D NULL) { + AmlDeleteNode ((AML_NODE_HEADER*)ArgCountNode); + } + + return Status; +} + +/** Get the number of arguments of a method invocation node. + + This function also allow to identify whether a node is a method invocati= on + node. If the input node is not a method invocation node, just return. + + @param [in] MethodInvocationNode Method invocation node. + @param [out] IsMethodInvocation Boolean stating whether the input + node is a method invocation. + @param [out] ArgCount Number of arguments of the method + invocation. + Set to 0 if MethodInvocationNode + is not a method invocation. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +EFI_STATUS +EFIAPI +AmlGetMethodInvocationArgCount ( + IN CONST AML_OBJECT_NODE * MethodInvocationNode, + OUT BOOLEAN * IsMethodInvocation, + OUT UINT8 * ArgCount + ) +{ + AML_DATA_NODE * NumArgsNode; + + if (!IS_AML_NODE_VALID (MethodInvocationNode) || + (IsMethodInvocation =3D=3D NULL) || + (ArgCount =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Check whether MethodInvocationNode is a method invocation. + if (!AmlNodeCompareOpCode (MethodInvocationNode, AML_METHOD_INVOC_OP, 0)= ) { + *IsMethodInvocation =3D FALSE; + *ArgCount =3D 0; + return EFI_SUCCESS; + } + + // MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount + // MethodInvocationOp :=3D Pseudo Opcode for Method Invocation + // NameString :=3D Method Name + // ArgumentCount :=3D ByteData (0 - 7) + NumArgsNode =3D (AML_DATA_NODE*)AmlGetFixedArgument ( + (AML_OBJECT_NODE*)MethodInvocationNode, + EAmlParseIndexTerm1 + ); + if (!IS_AML_NODE_VALID (NumArgsNode) || + (NumArgsNode->Buffer =3D=3D NULL) || + (NumArgsNode->DataType !=3D EAmlNodeDataTypeUInt) || + (NumArgsNode->Size !=3D 1)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + *ArgCount =3D *NumArgsNode->Buffer; + + *IsMethodInvocation =3D TRUE; + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.= h b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h new file mode 100644 index 0000000000000000000000000000000000000000..b082f2debde88da8a7dcabee7b4= a8b5003d4c592 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h @@ -0,0 +1,188 @@ +/** @file + AML Method Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_METHOD_PARSER_H_ +#define AML_METHOD_PARSER_H_ + +#include +#include + +/** AML namespace reference node. + + Namespace reference nodes allow to associate an AML absolute pathname + to the tree node defining this object in the namespace. + + Namespace reference nodes are stored in a separate list. They are not pa= rt of + the tree. +*/ +typedef struct AmlNameSpaceRefNode { + /// Double linked list. + /// This must be the first field in this structure. + LIST_ENTRY Link; + + /// Node part of the AML namespace. It must have the AML_IN_NAMESPACE + /// attribute. + CONST AML_OBJECT_NODE * NodeRef; + + /// Raw AML absolute pathname of the NodeRef. + /// This is a raw AML NameString (cf AmlNameSpace.c: A concatenated list + /// of 4 chars long names. The dual/multi NameString prefix have been + /// stripped.). + CONST CHAR8 * RawAbsolutePath; + + /// Size of the raw AML absolute pathname buffer. + UINT32 RawAbsolutePathSize; +} AML_NAMESPACE_REF_NODE; + +/** Delete a list of namespace reference nodes. + + @param [in] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteNameSpaceRefList ( + IN LIST_ENTRY * NameSpaceRefList + ); + + +#if !defined (MDEPKG_NDEBUG) +/** Print the list of raw absolute paths of the NameSpace reference list. + + @param [in] NameSpaceRefList List of NameSpace reference nodes. +**/ +VOID +EFIAPI +AmlDbgPrintNameSpaceRefList ( + IN CONST LIST_ENTRY * NameSpaceRefList + ); + +#endif // MDEPKG_NDEBUG + +/** Check whether a pathname is a method invocation. + + If there is a matching method definition, returns the corresponding + NameSpaceRef node. + + To do so, the NameSpaceRefList is keeping track of every namespace node + and its raw AML absolute path. + To check whether a pathname is a method invocation, a corresponding raw + absolute pathname is built. This raw absolute pathname is then compared + to the list of available pathnames. If a pathname defining a method + matches the scope of the input pathname, return. + + @param [in] ParentNode Parent node. Node to which the node to= be + created will be attached. + @param [in] FStream Forward stream pointing to the NameStr= ing + to find. + @param [in] NameSpaceRefList List of NameSpaceRef nodes. + @param [out] OutNameSpaceRefNode If the NameString pointed by FStream is + a method invocation, OutNameSpaceRefNo= de + contains the NameSpaceRef corresponding + to the method definition. + NULL otherwise. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlIsMethodInvocation ( + IN CONST AML_NODE_HEADER * ParentNode, + IN CONST AML_STREAM * FStream, + IN CONST LIST_ENTRY * NameSpaceRefList, + OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode + ); + +/** Create a namespace reference node and add it to the NameSpaceRefList. + + When a namespace node is encountered, the namespace it defines must be + associated to the node. This allow to keep track of the nature of each + name present in the AML namespace. + + In the end, this allows to recognize method invocations and parse the ri= ght + number of arguments after the method name. + + @param [in] Node Namespace node. + @param [in, out] NameSpaceRefList List of namespace reference nodes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlAddNameSpaceReference ( + IN CONST AML_OBJECT_NODE * Node, + IN OUT LIST_ENTRY * NameSpaceRefList + ); + +/** Create a method invocation node. + + The AML grammar does not attribute an OpCode/SubOpCode couple for + method invocations. This library is representing method invocations + as if they had one. + + The AML encoding for method invocations in the ACPI specification 6.3 is: + MethodInvocation :=3D NameString TermArgList + In this library, it is: + MethodInvocation :=3D MethodInvocationOp NameString ArgumentCount Term= ArgList + ArgumentCount :=3D ByteData + + When computing the size of a tree or serializing it, the additional data= is + not taken into account (i.e. the MethodInvocationOp and the ArgumentCoun= t). + + Method invocation nodes have the AML_METHOD_INVOVATION attribute. + + @param [in] NameSpaceRefNode NameSpaceRef node pointing to the + the definition of the invoked + method. + @param [in] MethodInvocationName Data node containing the method + invocation name. + @param [out] MethodInvocationNodePtr Created method invocation node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateMethodInvocationNode ( + IN CONST AML_NAMESPACE_REF_NODE * NameSpaceRefNode, + IN AML_DATA_NODE * MethodInvocationName, + OUT AML_OBJECT_NODE ** MethodInvocationNodePtr + ); + +/** Get the number of arguments of a method invocation node. + + This function also allow to identify whether a node is a method invocati= on + node. If the input node is not a method invocation node, just return. + + @param [in] MethodInvocationNode Method invocation node. + @param [out] IsMethodInvocation Boolean stating whether the input + node is a method invocation. + @param [out] ArgCount Number of arguments of the method + invocation. + Set to 0 if MethodInvocationNode + is not a method invocation. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +EFI_STATUS +EFIAPI +AmlGetMethodInvocationArgCount ( + IN CONST AML_OBJECT_NODE * MethodInvocationNode, + OUT BOOLEAN * IsMethodInvocation, + OUT UINT8 * ArgCount + ); + +#endif // AML_METHOD_PARSER_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64098): https://edk2.groups.io/g/devel/message/64098 Mute This Topic: https://groups.io/mt/76149182/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64097+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245838055533.6715328549413; Wed, 12 Aug 2020 08:23:58 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id LWTpYY1788612xMi8KyXTZBg; Wed, 12 Aug 2020 08:23:54 -0700 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com (EUR04-DB3-obe.outbound.protection.outlook.com [40.107.6.78]) by mx.groups.io with SMTP id smtpd.web11.17184.1597245826361922507 for ; Wed, 12 Aug 2020 08:23:46 -0700 X-Received: from AM5PR0202CA0009.eurprd02.prod.outlook.com (2603:10a6:203:69::19) by DB8PR08MB4025.eurprd08.prod.outlook.com (2603:10a6:10:a9::26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:43 +0000 X-Received: from VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:69:cafe::a6) by AM5PR0202CA0009.outlook.office365.com (2603:10a6:203:69::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:43 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64097+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT014.mail.protection.outlook.com (10.152.19.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:43 +0000 X-Received: ("Tessian outbound e8cdb8c6f386:v64"); Wed, 12 Aug 2020 15:23:43 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: e4e423fd4cdf70fc X-CR-MTA-TID: 64aa7808 X-Received: from 73fb849e2921.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 4778F146-E82F-464A-A4E6-3D98E6DDB186.1; Wed, 12 Aug 2020 15:23:38 +0000 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 73fb849e2921.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:38 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=A2UXc21NuRZLZ8KPfVikvFTK1IE87QmvqebIrFJ2RlKXG1xDOhQwF7nB57+M6jp3byY+UNk1v3r2i1/UqSohcQDN91UqXYl6cDF7ZH8vn+CuVUEEgPCxXPwl6PIPE8SgGY5Dmb4/AsiBC7/+vF12v1PQWRS9h4wH5Dzfqcwu2bx/inORspDkCgiX1l6Cugsc854VLqonTfqncuy64Wvy/sfegZsyEm9Dnj3x9RVY1KC8FC3PBx5178xCLpFI+1o6tg/vZcdYs/UvcoQSEeitOdMzB1RHYY8pZiTLZNgI1N2DFNhWUyj3ldqlyxkbQ12jZ6iXtLHA1HF+1VpxTm/Y9w== 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-SenderADCheck; bh=+FUj7411mvbNMA0OnFJTHB68/74neRvxkC3qYnn8KRk=; b=aXIs+n7Y+plVnnxM2lkSZmQ+OG3emdhN9wpZpubLVNgrHHxQtO3iiSCTrMwwqaESIRrmflIx8UZQDYka03TbOOmEQGANErwMQrZcAT2ShFcMtPexY2djRbBjuZPxu5QCxefOmXbDw/2UDlD4LKOqlSJ8IhctoScV4GjIFXYSnHdjdZZQ7M7QE9mxZYM6oqkpp7kh2vWfzBgfeObIPwwEiZG3iiyM52BUqz0WVT0R9uDm5IYElq42uvHpJbAEfPw2+BwfUHC1h0bgWF0smKnjkmEaTFm2oktQL1uPWjiznzDJ6wrMrK/tfnNPRyt2rGo20Ozr5LV7P3ru6TcAfBjVDQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB7PR05CA0001.eurprd05.prod.outlook.com (2603:10a6:10:36::14) by AM6PR08MB3560.eurprd08.prod.outlook.com (2603:10a6:20b:4c::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:36 +0000 X-Received: from DB5EUR03FT021.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:36:cafe::8) by DB7PR05CA0001.outlook.office365.com (2603:10a6:10:36::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:36 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT021.mail.protection.outlook.com (10.152.20.238) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:36 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:34 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:34 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 20/30] DynamicTablesPkg: AML Field list parser Date: Wed, 12 Aug 2020 16:22:26 +0100 Message-ID: <20200812152236.31164-21-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4a561062-e69d-4f5d-ec6b-08d83ed3b326 X-MS-TrafficTypeDiagnostic: AM6PR08MB3560:|DB8PR08MB4025: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:8273;OLM:8273; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(396003)(136003)(39860400002)(376002)(346002)(46966005)(81166007)(82310400002)(426003)(4326008)(2616005)(82740400003)(1076003)(356005)(86362001)(36756003)(47076004)(336012)(30864003)(186003)(7696005)(44832011)(70586007)(26005)(5660300002)(8676002)(8936002)(2906002)(83380400001)(6666004)(6916009)(54906003)(70206006)(316002)(478600001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3560 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: d39ee65a-cbf5-4f53-176d-08d83ed3ae9b X-Microsoft-Antispam-Message-Info: s+kNhQv9N0xht2A90IhQLLnj9O6hzyz5a2LTadOKaPqkaUCKilrQ6if2klbVPog2PsHURFvLhbijazpn+OqXJZRkOHgjvOkysGl9ZH5PuxgNU3gzdM0wPQy934eLyU7lpp21w6T0YA5gKZTY1srkMEVNTOpP+qCprWGyJmpd3+66sG8IbVQ/DJjOOFfKogEama6TAo4puUNlTtvx3WngpaUJ2JKNjHiNy3dt0+Aozrm9nJIUfSiP0wHSRJOkEqd/2jg+BZBIENSTFNeC5MEagIByVjb37gr0Gs0O5MZ3hi76u5ih2pu8Qm3/f29y1yCQoJYRJTEn0hIq74S9gJKz5jn+ysndJjcwXF75E/R57HruXeuhPCd2/bPvGCMKzAjorqeC1uzCAELOrFrCey4mcQ== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:43.6100 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4a561062-e69d-4f5d-ec6b-08d83ed3b326 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: VE1EUR03FT014.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB4025 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: mZxjLxuB8S74LKrdXSlVoMurx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245834; bh=MCpPDWhz58NuRy87z3L6SYLttO2PV9HSY+DapmVTxnY=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=tLep1lTZqEWwj6oUviV7F8CKeP3JUl2tOvDt9ZDJ7ZkkAKMVLg0IBTNOERUmeUlwqhO Vv+tp8z8/5AJW8J4cSxSp45nvjGyALwZjuZ2Jk++nFQmqH/QUvG7SXADLN9qAkehDbFM/ z4D9Nv6X/8m2b7R2X0XuUKsNTRXBvYF1Svo= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The AML language allows defining field lists in a Definition Block. Although Dynamic AML does not provide interfaces to modify Field Lists; an AML template code may contain Field lists and the AML parser must be capable of parsing and representing the Field lists in the AML tree. The AML parser creates an Object node that represents the 'Field Node'. The AML Field list parser creates an object node for each field element parsed in the AML byte stream, and adds them to the variable list of arguments of the 'Field Node'. Nodes that can have a field list are referred as 'Field nodes'. They have the AML_HAS_FIELD_LIST attribute set in the AML encoding. According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encoding", field elements can be: - NamedField :=3D NameSeg PkgLength; - ReservedField :=3D 0x00 PkgLength; - AccessField :=3D 0x01 AccessType AccessAttrib; - ConnectField :=3D <0x02 NameString> | <0x02 BufferData>; - ExtendedAccessField :=3D 0x03 AccessType ExtendedAccessAttrib AccessLength. A small set of opcodes describes the field elements. They are referred as field opcodes. An AML_BYTE_ENCODING table has been created for field OpCodes. Field elements: - don't have a SubOpCode; - have at most 3 fixed arguments (as opposed to 6 for standard AML objects); - don't have a variable list of arguments; - only the NamedField field element is part of the AML namespace. ConnectField's BufferData is a buffer node containing a single resource data element. NamedField field elements do not have an AML OpCode. NameSeg starts with a Char type and can thus be differentiated from the Opcodes for other fields. A pseudo OpCode has been created to simplify the parser. Following is a representation of a field node in an AML tree: (FieldNode) \ |- [0][1][3] # Fixed Arguments |- {(FldEl0)->(FldEl1)->...)} # Variable Arguments Where FldEl[n] is one of NamedField, ReservedField, AccessField, ConnectField, ExtendedAccessField. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c | 375 += +++++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h | 77 += +++ 2 files changed, 452 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListPars= er.c b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c new file mode 100644 index 0000000000000000000000000000000000000000..c25ee22dc7c4b22b1448e11cf9b= bd4e5e77c4316 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c @@ -0,0 +1,375 @@ +/** @file + AML Field List Parser. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include + +/** Parse a field element. + + The field elements this function can parse are one of: + - ReservedField; + - AccessField; + - ConnectField; + - ExtendedAccessField. + Indeed, the NamedField field element doesn't have an OpCode. Thus it nee= ds + to be parsed differently. + + @param [in] FieldByteEncoding Field byte encoding to parse. + @param [in, out] FieldNode Field node to attach the field + element to. + Must have the AML_HAS_FIELD_LI= ST + attribute. + @param [in, out] FStream Forward stream pointing to a f= ield + element not being a named fiel= d. + The stream must not be at its = end. + @param [in, out] NameSpaceRefList List of namespace reference no= des, + allowing to associate an absol= ute + path to a node in the tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlParseFieldElement ( + IN CONST AML_BYTE_ENCODING * FieldByteEncoding, + IN OUT AML_OBJECT_NODE * FieldNode, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + UINT8 * CurrPos; + AML_OBJECT_NODE * NewNode; + + UINT32 PkgLenOffset; + UINT32 PkgLenSize; + + // Check whether the node is an Object Node and has a field list. + // The byte encoding must be a field element. + if ((FieldByteEncoding =3D=3D NULL) || + ((FieldByteEncoding->Attribute & AML_IS_FIELD_ELEMENT) =3D=3D 0) || + ((FieldByteEncoding->Attribute & AML_IS_PSEUDO_OPCODE) =3D=3D + AML_IS_PSEUDO_OPCODE) || + !AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CurrPos =3D AmlStreamGetCurrPos (FStream); + if (CurrPos =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Skip the field opcode (1 byte) as it is already in the FieldByteEncod= ing. + DumpRaw (CurrPos, 1); + Status =3D AmlStreamProgress (FStream, 1); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + CurrPos =3D AmlStreamGetCurrPos (FStream); + if (CurrPos =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Parse the PkgLen if available. + PkgLenSize =3D 0; + if ((FieldByteEncoding->Attribute & AML_HAS_PKG_LENGTH) =3D=3D + AML_HAS_PKG_LENGTH) { + PkgLenOffset =3D AmlGetPkgLength (CurrPos, &PkgLenSize); + if (PkgLenOffset =3D=3D 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Move stream forward as the PkgLen has been read. + DumpRaw (CurrPos, PkgLenOffset); + Status =3D AmlStreamProgress (FStream, PkgLenOffset); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Update the current position as PkgLen has been parsed. + CurrPos =3D AmlStreamGetCurrPos (FStream); + } + + Status =3D AmlCreateObjectNode ( + FieldByteEncoding, + PkgLenSize, + &NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the FieldElement to the Variable Argument List. + Status =3D AmlVarListAddTailInternal ( + (AML_NODE_HEADER*)FieldNode, + (AML_NODE_HEADER*)NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + // Delete the sub-tree if the insertion failed. + // Otherwise its reference will be lost. + AmlDeleteTree ((AML_NODE_HEADER*)NewNode); + return Status; + } + + // Some field elements do not have fixed arguments. + if (!IS_END_OF_STREAM (FStream)) { + // Parse the fixed arguments of the field element. + Status =3D AmlParseFixedArguments ( + NewNode, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + } + + return Status; +} + +/** Parse a named field element. + + Indeed, the NamedField field element doesn't have an OpCode. Thus it nee= ds + to be parsed differently. NamedField field element start with a char. + + @param [in] NamedFieldByteEncoding Field byte encoding to parse. + @param [in, out] FieldNode Field node to attach the field + element to. + Must have the AML_HAS_FIELD_LI= ST + attribute. + @param [in, out] FStream Forward stream pointing to a n= amed + field element. + The stream must not be at its = end. + @param [in, out] NameSpaceRefList List of namespace reference no= des, + allowing to associate an absol= ute + path to a node in the tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +*/ +STATIC +EFI_STATUS +EFIAPI +AmlParseNamedFieldElement ( + IN CONST AML_BYTE_ENCODING * NamedFieldByteEncoding, + IN OUT AML_OBJECT_NODE * FieldNode, + IN OUT AML_STREAM * FStream, + IN OUT LIST_ENTRY * NameSpaceRefList +) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * NewNode; + + // Check whether the node is an Object Node and has a field list. + // The byte encoding must be a char. + if ((NamedFieldByteEncoding =3D=3D NULL) || + ((NamedFieldByteEncoding->Attribute & AML_IS_NAME_CHAR) =3D=3D 0) || + !AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Create a NamedField node. + Status =3D AmlCreateObjectNode ( + AmlGetFieldEncodingByOpCode (AML_FIELD_NAMED_OP, 0), + 0, + &NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the NamedField node to the variable argument list. + Status =3D AmlVarListAddTailInternal ( + (AML_NODE_HEADER*)FieldNode, + (AML_NODE_HEADER*)NewNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + // Delete the sub-tree if the insertion failed. + // Otherwise its reference will be lost. + AmlDeleteTree ((AML_NODE_HEADER*)NewNode); + return Status; + } + + // Parse the fixed arguments: [0]NameSeg, [1]PkgLen. + Status =3D AmlParseFixedArguments ( + NewNode, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the NamedField to the namespace reference list. + Status =3D AmlAddNameSpaceReference ( + NewNode, + NameSpaceRefList + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Parse the FieldList contained in the stream. + + Create an object node for each field element parsed in the field list + available in the Stream, and add them to the variable list of arguments + of the FieldNode. + + Nodes that can have a field list are referred as field nodes. They have = the + AML_HAS_FIELD_LIST attribute. + + According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encodi= ng", + field elements can be: + - NamedField :=3D NameSeg PkgLength; + - ReservedField :=3D 0x00 PkgLength; + - AccessField :=3D 0x01 AccessType AccessAttrib; + - ConnectField :=3D <0x02 NameString> | <0x02 BufferData>; + - ExtendedAccessField :=3D 0x03 AccessType ExtendedAccessAttrib Access= Length. + + A small set of opcodes describes the field elements. They are referred as + field opcodes. An AML_BYTE_ENCODING table has been created for field OpC= odes. + Field elements: + - don't have a SubOpCode; + - have at most 3 fixed arguments (as opposed to 6 for standard AML obje= cts); + - don't have a variable list of arguments; + - only the NamedField field element is part of the AML namespace. + + ConnectField's BufferData is a buffer node containing a single + resource data element. + NamedField field elements don't have an AML OpCode. NameSeg starts with a + Char type and can thus be differentiated from the Opcodes for other fiel= ds. + A pseudo OpCode has been created to simplify the parser. + + The branch created from parsing a field node is as: + (FieldNode) + \ + |- [FixedArg[0]][FixedArg[1]] # Fixed Arguments + |- {(FieldElement[0])->(FieldElement[1])->...)} # Variable Argum= ents + + With FieldElement[n] being one of NamedField, ReservedField, AccessField, + ConnectField, ExtendedAccessField. + + @param [in] FieldNode Field node. + Must have the AML_HAS_FIELD_LIST + attribute. + @param [in] FStream Forward stream pointing to a field list. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes, + allowing to associate an absolute + path to a node in the tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseFieldList ( + IN AML_OBJECT_NODE * FieldNode, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ) +{ + EFI_STATUS Status; + + UINT8 * CurrPos; + CONST AML_BYTE_ENCODING * FieldByteEncoding; + CONST AML_BYTE_ENCODING * NamedFieldByteEncoding; + + // Check whether the node is an Object Node and has a field list. + if (!AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) || + !IS_STREAM (FStream) || + IS_END_OF_STREAM (FStream) || + !IS_STREAM_FORWARD (FStream) || + (NameSpaceRefList =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Iterate through the field elements, creating nodes + // and adding them to the variable list of elements of Node. + while (!IS_END_OF_STREAM (FStream)) { + CurrPos =3D AmlStreamGetCurrPos (FStream); + + // Check for a field opcode. + FieldByteEncoding =3D AmlGetFieldEncoding (CurrPos); + if (FieldByteEncoding !=3D NULL) { + Status =3D AmlParseFieldElement ( + FieldByteEncoding, + FieldNode, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } else { + // Handle the case of Pseudo OpCodes. + // NamedField has a Pseudo OpCode and starts with a NameChar. Theref= ore, + // call AmlGetByteEncoding() to check that the encoding is NameChar. + NamedFieldByteEncoding =3D AmlGetByteEncoding (CurrPos); + if ((NamedFieldByteEncoding !=3D NULL) && + (NamedFieldByteEncoding->Attribute & AML_IS_NAME_CHAR)) { + // This is a NamedField field element since it is starting with a = char. + Status =3D AmlParseNamedFieldElement ( + NamedFieldByteEncoding, + FieldNode, + FStream, + NameSpaceRefList + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } else { + // A field opcode or an AML byte encoding is expected. + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + } // while + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListPars= er.h b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h new file mode 100644 index 0000000000000000000000000000000000000000..576f6c41d5620468b524b62684f= 67af1dacee24d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h @@ -0,0 +1,77 @@ +/** @file + AML Field List. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_FIELD_LIST_PARSER_H_ +#define AML_FIELD_LIST_PARSER_H_ + +#include +#include + +/** Parse the FieldList contained in the stream. + + Create an object node for each field element parsed in the field list + available in the Stream, and add them to the variable list of arguments + of the FieldNode. + + Nodes that can have a field list are referred as field nodes. They have = the + AML_HAS_FIELD_LIST attribute. + + According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encodi= ng", + field elements can be: + - NamedField :=3D NameSeg PkgLength; + - ReservedField :=3D 0x00 PkgLength; + - AccessField :=3D 0x01 AccessType AccessAttrib; + - ConnectField :=3D <0x02 NameString> | <0x02 BufferData>; + - ExtendedAccessField :=3D 0x03 AccessType ExtendedAccessAttrib Access= Length. + + A small set of opcodes describes the field elements. They are referred as + field opcodes. An AML_BYTE_ENCODING table has been created for field OpC= odes. + Field elements: + - don't have a SubOpCode; + - have at most 3 fixed arguments (as opposed to 6 for standard AML obje= cts); + - don't have a variable list of arguments; + - only the NamedField field element is part of the AML namespace. + + ConnectField's BufferData is a buffer node containing a single + resource data element. + NamedField field elements don't have an AML OpCode. NameSeg starts with a + Char type and can thus be differentiated from the Opcodes for other fiel= ds. + A pseudo OpCode has been created to simplify the parser. + + The branch created from parsing a field node is as: + (FieldNode) + \ + |- [FixedArg[0]][FixedArg[1]] # Fixed Arguments + |- {(FieldElement[0])->(FieldElement[1])->...)} # Variable Argum= ents + + With FieldElement[n] being one of NamedField, ReservedField, AccessField, + ConnectField, ExtendedAccessField. + + @param [in] FieldNode Field node. + Must have the AML_HAS_FIELD_LIST + attribute. + @param [in] FStream Forward stream pointing to a field list. + The stream must not be at its end. + @param [in] NameSpaceRefList List of namespace reference nodes, + allowing to associate an absolute + path to a node in the tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseFieldList ( + IN AML_OBJECT_NODE * FieldNode, + IN AML_STREAM * FStream, + IN LIST_ENTRY * NameSpaceRefList + ); + +#endif // AML_FIELD_LIST_PARSER_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64097): https://edk2.groups.io/g/devel/message/64097 Mute This Topic: https://groups.io/mt/76149177/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64102+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245846833244.33210205326918; Wed, 12 Aug 2020 08:24:06 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id I0QqYY1788612xfqzYc405M2; Wed, 12 Aug 2020 08:24:02 -0700 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com (EUR05-DB8-obe.outbound.protection.outlook.com [40.107.20.48]) by mx.groups.io with SMTP id smtpd.web11.17186.1597245834309805901 for ; Wed, 12 Aug 2020 08:23:54 -0700 X-Received: from AM6P193CA0132.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::37) by AM6PR08MB4310.eurprd08.prod.outlook.com (2603:10a6:20b:b8::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.15; Wed, 12 Aug 2020 15:23:45 +0000 X-Received: from AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:85:cafe::a4) by AM6P193CA0132.outlook.office365.com (2603:10a6:209:85::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:45 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64102+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT023.mail.protection.outlook.com (10.152.16.169) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:45 +0000 X-Received: ("Tessian outbound 195a290eb161:v64"); Wed, 12 Aug 2020 15:23:45 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: e3ddd9ffbc240f30 X-CR-MTA-TID: 64aa7808 X-Received: from 8a7c49420ad1.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 5C42C488-C2DE-4161-8B56-7CB28A7F6FD3.1; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 8a7c49420ad1.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:39 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=e3HGZiqyjU6sgtR0/sbxMvo3DKnrJ468sfKNIPwv5WQKsWTuMA4i01fp7aaX+ccpm3PcNy6hbNc7wyNI7RRvaFthzxdNPblA5hyQ23RdSVtWtgIMMW3agpvA0jg+LlJxqVcFs1XShjA3gso346SXBltievVNMtkMyPqd5OlsX3bZ9k8fMT7m1qIRb1bvH2uuZ+/1e9b0e7n2xAjY6YncBR2tcCPuXbOwXCxmZpno7zpOhsMNPhe6zfMj/F2/75jryXfrt22GzM1Cig/OpoX1rQKVjAg2dRv55c0PdMyCLP7Rs82GHQlUO2TCrj5xYwYp6ALYW0w6OEjXQPoa0QUQsA== 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-SenderADCheck; bh=G/XvKrGpkHmmu6GGZ6lOswxLD/Sqvg27tPfHZ+Wt4vw=; b=lI9NFVuyxTnlnL0qMJOv0046J7lJUsJDlgXpajsA1QsTIrZxr0Qmvn+sKg23dMU1L3S0+S3JckMmNrJ+s0TR4hMjdeSdm7VA85Iox4A9KofMjJjR7dT99IvjRxfa/rexBmg58633PzSXuYYgg6yhcG5foORNkypIxUZ23eDaD47lmP7YVspSaFpUq5R+2iMJtWy9ONczFiJeOGYki7+nwkjQdR/FMC+/9xJTBHYtVZxvkAJwt3ECL2H6LqrEHVyHQz+sQaEHKmfSe7Bzp6VlStEvP9Bgy0WH7v+EJBxZLCuQL47n93frqGt5s4hYo8ZQfengRdfSr0VWXTVh2G0dTA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0061.eurprd07.prod.outlook.com (2603:10a6:6:2a::23) by DB8PR08MB5129.eurprd08.prod.outlook.com (2603:10a6:10:ec::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:38 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::2b) by DB6PR07CA0061.outlook.office365.com (2603:10a6:6:2a::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3305.10 via Frontend Transport; Wed, 12 Aug 2020 15:23:38 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:38 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:36 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:35 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 21/30] DynamicTablesPkg: AML Codegen Date: Wed, 12 Aug 2020 16:22:27 +0100 Message-ID: <20200812152236.31164-22-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e27f8d63-09cb-4232-6ba4-08d83ed3b429 X-MS-TrafficTypeDiagnostic: DB8PR08MB5129:|AM6PR08MB4310: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:8273;OLM:8273; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: sgWPQMPCMZsaRYuzwRxGDC/zKzl/DRNNCYDA+aO4wW/usSBj+AanYDNNGo+QmwACvqfGTY3vbKLzZeTE7DQGmYqiiSmKGmRTwcBzL/julYQmOHzPuRvRocDC5ponvfLtX++xI27hum7z8Gk/6Z50ei2CKfQi/GzpruLkAQDjJeJw80xNNBSQGUhsPi/H4+mJZgsoq6Gxfy8DNhwf425Fls+PxxJQZYTIWKkVkpWcPi9A0HJcdOr3ZN684U007Jr9c6On1mq+khWSnLmdmTMgnLP+lacrfgx7whieWLZLbPbstRZPKnTgPZZJqg6bbh+0qKCfcrwo5qgyUHaQs7FHTsFEjcXBaZxnKftcIRI0yxDLZ8TevwzMgk2i7KEr5uwJ0ZWZ6igiAdJerb7AflttPQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(136003)(346002)(396003)(39860400002)(376002)(46966005)(2906002)(36756003)(8936002)(82740400003)(30864003)(316002)(54906003)(4326008)(47076004)(5660300002)(6916009)(1076003)(70206006)(70586007)(81166007)(7696005)(26005)(2616005)(186003)(82310400002)(86362001)(44832011)(478600001)(83380400001)(8676002)(356005)(426003)(6666004)(336012);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB5129 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: cee7da57-d20f-4c80-7fec-08d83ed3afea X-Microsoft-Antispam-Message-Info: GlKfnLJ7y9aE9pr+jB5YuBCbvoI6UTocPN//pn4f1ra90q0cgyC3cnHxlyePDh39cvgEppSMGwW/Z7Qh9vwW5F8wepqHd0ptoG3xsbCm6Dd3chMgGwQ4NPlmqGOKfDeSf4ke4BAdeH3HvEgmshC41hArCPCyvj81R/5JTw8KIh51Yn45FvC6ARJkEGU4LgvVU3luySYeeZ1iPJhp30z54rIAsh+YONybQqKj6s/Yr1FfE4EFE9vYc+m9x89h8x5Uj7tzlUMvp4DkmPQbmUX2/jK/alu3ypCbrKm0wal+EegHYRUWWB1OFZ5uDZhp3LHc/2wuC7RQL9DToT6+FPZwB6+G3k3cPI2YsbQZy0soZfZSg86u86XFjUMptQMLaThVBHHr2v6goIwaxex9NL3qPg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:45.3980 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e27f8d63-09cb-4232-6ba4-08d83ed3b429 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: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB4310 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: ZLm1tv4enVMJPlP6K9xAFoiNx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245842; bh=oe6YLqZXudyV8CSBspDg9FA8FCePf4Gva12eZh2nIZ4=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=Qa5STHtlt7KiM4bnXPrVkxxr2ZOaxWyZ0Q8QG1BevyvdLoTU/6YCUMIL6UhU2Vsv1b6 A1gclS7fB5HoXH6jRzCYPZCOf8/R7bQLb3MX97wJI5csE+/uSh8T7QuhmYgR52iCTbNPY zmLhJ9495xnfE/KafMM0Fz4TV6F9vs36a8k= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML Codegen is a Dynamic AML technique that facilitates generation of small segments of AML code. The AML code generated using AML Codegen is represented as nodes in the AML Tree. Some examples where AML Codegen can be used are: - AML Codegen APIs can be used to generate a simple AML tree. - An AML template can be parsed to create an AML tree. This AML Tree can be searched to locate a node that needs updating. The AML Codegen APIs can be used to attach new AML nodes. - A combination of AML Fixup and AML Codegen can be used to generate an AML tree. The AML tree can then be serialised as a Definition Block table. Following AML Codegen APIs are implemented: - AmlCodeGenDefinitionBlock() - AmlCodeGenScope() - AmlCodeGenNameString() - AmlCodeGenNameInteger() - AmlCodeGenDevice() These AML Codegen APIs in combination with AML Resource Data Codegen APIs can be used to generate a simple AML tree. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c | 701 ++++++++= ++++++++++++ 1 file changed, 701 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/= DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c new file mode 100644 index 0000000000000000000000000000000000000000..d6d9f5dfe839aa8ef79153459ec= 9d2c2ffe72316 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -0,0 +1,701 @@ +/** @file + AML Code Generation. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/** Utility function to link a node when returning from a CodeGen function. + + @param [in] Node Newly created node. + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewObjectNode If success, contains the created object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +LinkNode ( + IN AML_OBJECT_NODE * Node, + IN AML_NODE_HEADER * ParentNode, + IN AML_OBJECT_NODE ** NewObjectNode + ) +{ + EFI_STATUS Status; + + if (NewObjectNode !=3D NULL) { + *NewObjectNode =3D Node; + } + + // Add RdNode as the last element. + if (ParentNode !=3D NULL) { + Status =3D AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** AML code generation for DefinitionBlock. + + Create a Root Node handle. + It is the caller's responsibility to free the allocated memory + with the AmlDeleteTree function. + + AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) = is + equivalent to the following ASL code: + DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision, + OemID, TableID, OEMRevision) {} + with the ComplianceRevision set to 2 and the AMLFileName is ignored. + + @param[in] TableSignature 4-character ACPI signature. + Must be 'DSDT' or 'SSDT'. + @param[in] OemId 6-character string OEM identifier. + @param[in] OemTableId 8-character string OEM table identifier. + @param[in] OemRevision OEM revision number. + @param[out] DefinitionBlockTerm The ASL Term handle representing a + Definition Block. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenDefinitionBlock ( + IN CONST CHAR8 * TableSignature, + IN CONST CHAR8 * OemId, + IN CONST CHAR8 * OemTableId, + IN UINT32 OemRevision, + OUT AML_ROOT_NODE ** NewRootNode + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER AcpiHeader; + + if ((TableSignature =3D=3D NULL) || + (OemId =3D=3D NULL) || + (OemTableId =3D=3D NULL) || + (NewRootNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CopyMem (&AcpiHeader.Signature, TableSignature, 4); + AcpiHeader.Length =3D sizeof (EFI_ACPI_DESCRIPTION_HEADER); + AcpiHeader.Revision =3D 2; + CopyMem (&AcpiHeader.OemId, OemId, 6); + CopyMem (&AcpiHeader.OemTableId, OemTableId, 8); + AcpiHeader.OemRevision =3D OemRevision; + AcpiHeader.CreatorId =3D TABLE_GENERATOR_CREATOR_ID_ARM; + AcpiHeader.CreatorRevision =3D CREATE_REVISION (1, 0); + + Status =3D AmlCreateRootNode (&AcpiHeader, NewRootNode); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** AML code generation for a String object node. + + @param [in] String Pointer to a NULL terminated string. + @param [out] NewObjectNode If success, contains the created + String object node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCodeGenString ( + IN CHAR8 * String, + OUT AML_OBJECT_NODE ** NewObjectNode + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + AML_DATA_NODE * DataNode; + + if ((String =3D=3D NULL) || + (NewObjectNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ObjectNode =3D NULL; + DataNode =3D NULL; + + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0), + 0, + &ObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeString, + (UINT8*)String, + (UINT32)AsciiStrLen (String) + 1, + &DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + Status =3D AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)DataNode); + goto error_handler; + } + + *NewObjectNode =3D ObjectNode; + return Status; + +error_handler: + if (ObjectNode !=3D NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + + return Status; +} + +/** AML code generation for an Integer object node. + + @param [in] Integer Integer of the Integer object node. + @param [out] NewObjectNode If success, contains the created + Integer object node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCodeGenInteger ( + IN UINT64 Integer, + OUT AML_OBJECT_NODE ** NewObjectNode + ) +{ + EFI_STATUS Status; + INT8 ValueWidthDiff; + + if (NewObjectNode =3D=3D NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Create an object node containing Zero. + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0), + 0, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Update the object node with integer value. + Status =3D AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthD= iff); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode); + } + + return Status; +} + +/** AML code generation for a Name object node. + + @param [in] NameString The new variable name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + This input string is copied. + @param [in] Object Object associated to the NameString. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlCodeGenName ( + IN CONST CHAR8 * NameString, + IN AML_OBJECT_NODE * Object, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + AML_DATA_NODE * DataNode; + CHAR8 * AmlNameString; + UINT32 AmlNameStringSize; + + if ((NameString =3D=3D NULL) || + (Object =3D=3D NULL) || + ((ParentNode =3D=3D NULL) && (NewObjectNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ObjectNode =3D NULL; + DataNode =3D NULL; + AmlNameString =3D NULL; + + Status =3D ConvertAslNameToAmlName (NameString, &AmlNameString); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlGetNameStringSize (AmlNameString, &AmlNameStringSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_NAME_OP, 0), + 0, + &ObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeNameString, + (UINT8*)AmlNameString, + AmlNameStringSize, + &DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + Status =3D AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)DataNode); + goto error_handler2; + } + + Status =3D AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm1, + (AML_NODE_HEADER*)Object + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + Status =3D LinkNode ( + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + // Free AmlNameString before returning as it is copied + // in the call to AmlCreateDataNode(). + goto error_handler1; + +error_handler2: + if (ObjectNode !=3D NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + +error_handler1: + if (AmlNameString !=3D NULL) { + FreePool (AmlNameString); + } + + return Status; +} + +/** AML code generation for a Name object node, containing a String. + + AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Name(_HID, "HID0000") + + @param [in] NameString The new variable name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @param [in] String NULL terminated String to associate to the + NameString. + @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 +AmlCodeGenNameString ( + IN CONST CHAR8 * NameString, + IN CHAR8 * String, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + + if ((NameString =3D=3D NULL) || + (String =3D=3D NULL) || + ((ParentNode =3D=3D NULL) && (NewObjectNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCodeGenString (String, &ObjectNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlCodeGenName ( + NameString, + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + + return Status; +} + +/** AML code generation for a Name object node, containing an Integer. + + AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Name(_UID, One) + + @param [in] NameString The new variable name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @param [in] Integer Integer to associate to the NameString. + @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 +AmlCodeGenNameInteger ( + IN CONST CHAR8 * NameString, + IN UINT64 Integer, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + + if ((NameString =3D=3D NULL) || + ((ParentNode =3D=3D NULL) && (NewObjectNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D AmlCodeGenInteger (Integer, &ObjectNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlCodeGenName ( + NameString, + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + + return Status; +} + +/** AML code generation for a Device object node. + + AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Device(COM0) {} + + @param [in] NameString The new Device's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @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 +AmlCodeGenDevice ( + IN CONST CHAR8 * NameString, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + AML_DATA_NODE * DataNode; + CHAR8 * AmlNameString; + UINT32 AmlNameStringSize; + + if ((NameString =3D=3D NULL) || + ((ParentNode =3D=3D NULL) && (NewObjectNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ObjectNode =3D NULL; + DataNode =3D NULL; + AmlNameString =3D NULL; + + Status =3D ConvertAslNameToAmlName (NameString, &AmlNameString); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlGetNameStringSize (AmlNameString, &AmlNameStringSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP), + AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSi= ze), + &ObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeNameString, + (UINT8*)AmlNameString, + AmlNameStringSize, + &DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + Status =3D AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)DataNode); + goto error_handler2; + } + + Status =3D LinkNode ( + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + // Free AmlNameString before returning as it is copied + // in the call to AmlCreateDataNode(). + goto error_handler1; + +error_handler2: + if (ObjectNode !=3D NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + +error_handler1: + if (AmlNameString !=3D NULL) { + FreePool (AmlNameString); + } + + return Status; +} + +/** AML code generation for a Scope object node. + + AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Scope(_SB) {} + + @param [in] NameString The new Scope's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @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 +AmlCodeGenScope ( + IN CONST CHAR8 * NameString, + IN AML_NODE_HEADER * ParentNode, OPTIONAL + OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE * ObjectNode; + AML_DATA_NODE * DataNode; + CHAR8 * AmlNameString; + UINT32 AmlNameStringSize; + + if ((NameString =3D=3D NULL) || + ((ParentNode =3D=3D NULL) && (NewObjectNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + ObjectNode =3D NULL; + DataNode =3D NULL; + AmlNameString =3D NULL; + + Status =3D ConvertAslNameToAmlName (NameString, &AmlNameString); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlGetNameStringSize (AmlNameString, &AmlNameStringSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateObjectNode ( + AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0), + AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSi= ze), + &ObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler1; + } + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeNameString, + (UINT8*)AmlNameString, + AmlNameStringSize, + &DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + Status =3D AmlSetFixedArgument ( + ObjectNode, + EAmlParseIndexTerm0, + (AML_NODE_HEADER*)DataNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + AmlDeleteTree ((AML_NODE_HEADER*)DataNode); + goto error_handler2; + } + + Status =3D LinkNode ( + ObjectNode, + ParentNode, + NewObjectNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler2; + } + + // Free AmlNameString before returning as it is copied + // in the call to AmlCreateDataNode(). + goto error_handler1; + +error_handler2: + if (ObjectNode !=3D NULL) { + AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode); + } + +error_handler1: + if (AmlNameString !=3D NULL) { + FreePool (AmlNameString); + } + + return Status; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64102): https://edk2.groups.io/g/devel/message/64102 Mute This Topic: https://groups.io/mt/76149187/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64104+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245848481816.6067057151572; Wed, 12 Aug 2020 08:24:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5fxSYY1788612xABNpJgbgzl; Wed, 12 Aug 2020 08:24:07 -0700 X-Received: from EUR01-DB5-obe.outbound.protection.outlook.com (EUR01-DB5-obe.outbound.protection.outlook.com [40.107.15.58]) by mx.groups.io with SMTP id smtpd.web12.16985.1597245835974108691 for ; Wed, 12 Aug 2020 08:23:56 -0700 X-Received: from AM6P195CA0108.EURP195.PROD.OUTLOOK.COM (2603:10a6:209:86::49) by HE1PR0802MB2460.eurprd08.prod.outlook.com (2603:10a6:3:dd::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:52 +0000 X-Received: from VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:86:cafe::b4) by AM6P195CA0108.outlook.office365.com (2603:10a6:209:86::49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:52 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64104+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT005.mail.protection.outlook.com (10.152.18.172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:51 +0000 X-Received: ("Tessian outbound 7a6fb63c1e64:v64"); Wed, 12 Aug 2020 15:23:51 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 90b06eda58a0e0d9 X-CR-MTA-TID: 64aa7808 X-Received: from c20a0246022e.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id A9311265-41A3-4C37-8F4D-B8A8926F32F3.1; Wed, 12 Aug 2020 15:23:46 +0000 X-Received: from EUR03-VE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id c20a0246022e.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:46 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hl2VgBn2MqOxh4CljYT83b0pALD92EvS4d13vfTml3mU0oKZuzq2Po6B5QNARQAHeeT7xosu7LrUEcZ2AeJnolK3qR0Rh/vbPgo/WNoqu7/PfGHyrFX4QC17uDckiC2yo2JWEH3BW7rl6UqrzJNTiu7reDDCgVsPoS1SdaO2hIaGMNU5+Ih6EwzHZHpWn8iceajRxvh5efdGlOus1EES9+L8Ntpfsj3y2IfL+yYeSR1sML07qVuxuDX1oymYmLEnvddDjKEto1Do++XvJDBZ1JbskPUQcga2WBIGPk8n0Jmn1aRKDejN8gI8yEPXwh12J90jpHHYLjMrwJqvEzdlQQ== 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-SenderADCheck; bh=4PObdGNzp62KBu51lW1e5DxOkzDf5njJBVUUbLRiQmQ=; b=jmfsZBLi4q1ofM2B4Wqb1908pHXmGwQHGSjFwf/Gvd55H3X6c52/WXoJi9sDxTafoaELclurtMjROhWek2PNV1rW8mMgaYwm8AYkElf5f+FiKUQejQSWWF266HhA+HzuYcMxEvQT9bOipMe2TyFvaWm3BYYsHMAjwmoovegFZd6SuCYSz2IeikNm9oB8zEhRshERPy/4Y7JhPQ71ifcCp87LmW72bUw01gwol/nTq3t7z9bA/qnRp2N+oqFoNQLjgY7ex4zCZqUvJWa4YfG3WoZT62EPoBKAFXI03A1NYRP7J8rVQi56KX5vFY+XTGkDSGAUWB8OY9whcHAJSXAjYQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0066.eurprd07.prod.outlook.com (2603:10a6:6:2a::28) by DB7PR08MB3785.eurprd08.prod.outlook.com (2603:10a6:10:32::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::3a) by DB6PR07CA0066.outlook.office365.com (2603:10a6:6:2a::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.10 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:36 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:36 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 22/30] DynamicTablesPkg: AML Resource Data Codegen Date: Wed, 12 Aug 2020 16:22:28 +0100 Message-ID: <20200812152236.31164-23-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f775c230-8fd4-48a4-1284-08d83ed3b807 X-MS-TrafficTypeDiagnostic: DB7PR08MB3785:|HE1PR0802MB2460: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:3173;OLM:3173; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(136003)(39860400002)(346002)(376002)(396003)(46966005)(5660300002)(82740400003)(19627235002)(86362001)(47076004)(186003)(336012)(316002)(6916009)(36756003)(82310400002)(54906003)(26005)(2906002)(70586007)(30864003)(426003)(70206006)(8676002)(81166007)(6666004)(44832011)(83380400001)(478600001)(356005)(4326008)(2616005)(1076003)(7696005)(8936002);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3785 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 3ff8d287-ce2a-46c5-4f12-08d83ed3b061 X-Microsoft-Antispam-Message-Info: Mcv8b55aHhqRi8/s0LHNfN3gZIBqebfFsdaOLavOj2RYSZ+UIJH0y9F9kzo5FyTFdE/jIV7TTFFuAkX20Tnh2cuG8qjW4lnDiWZ7rExG1LeBXxhAkHyygDiqsI1xpQxBt3SVfNLg1SYogVGuOUfZPvPYejwdHJcbFz8qKXzXWEbVs4WV6CKhE3Nv+31CpKeCCgY0yXPE397JHlGBfm0AfuU5f8lBYKBpskYNCwzcvrh2YAK6ES5TM+CR4NFI3jVWBvAATMGbUCr/iMuiAWotQ45sckpcTLvxOWHc5qdV/NWm0qUUAlr8dvFl0IZqfGsmn1Bo1P/ONwBUtnIMYtD4Wuc5uF75CVpORktYdDpqv2eEXBLXSgAX280OG9m/G1YdeEsKtNJSFf4aE2NLyPq3/w== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:51.7905 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f775c230-8fd4-48a4-1284-08d83ed3b807 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: VE1EUR03FT005.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0802MB2460 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: BYZcqwVy9aI6xN4uf4jcChBQx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245847; bh=BAUfLkmSfVfKzz6iPD7GWZD5GuaTu178kKM3sTwjj2c=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=qOJvg81hzK4AOfiaJ2TEBmZBmCbZc9FY69dY83KByhNcUh0lXW9GPeYA+eHlwvpFeoD IieKtzs3uVpoR6CUtEJr+H4sMJyxtL4CuE71KdCUi6siLagbLezYuISG3fDTUAQkC1nij sPDQUjGG4temMs0q17D21xRY1H0aoFOFkIU= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML Codegen is a Dynamic AML technique that facilitates generation of small segments of AML code. The AML code generated using AML Codegen is represented as nodes in the AML Tree. AML Resource Data Codegen implements interfaces required for generating Resource Data elements that can be attached to an AML tree. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c | = 256 ++++++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h | = 59 +++++ 2 files changed, 315 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceData= CodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataC= odeGen.c new file mode 100644 index 0000000000000000000000000000000000000000..9e7a508e60721558ab59b375dbd= 526c7066d7329 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen= .c @@ -0,0 +1,256 @@ +/** @file + AML Resource Data Code Generation. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rd or RD - Resource Data + - Rds or RDS - Resource Data Small + - Rdl or RDL - Resource Data Large +**/ + +#include +#include + +#include +#include +#include +#include +#include + +/** If ParentNode is not NULL, append RdNode. + If NewRdNode is not NULL, update its value to RdNode. + + @param [in] RdNode Newly created Resource Data node. + @param [in] ParentNode If not NULL, add the generated node + to the end of the variable list of + argument of the ParentNode, but + before the "End Tag" Resource Data. + Must be a BufferOpNode. + @param [out] NewRdNode If not NULL, update the its value to RdNode. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +LinkRdNode ( + IN AML_DATA_NODE * RdNode, + IN AML_OBJECT_NODE * ParentNode, + IN AML_DATA_NODE ** NewRdNode + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + + if (NewRdNode !=3D NULL) { + *NewRdNode =3D RdNode; + } + + // Add RdNode as the last element, but before the EndTag. + if (ParentNode !=3D NULL) { + Status =3D AmlAppendRdNode (ParentNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + Status1 =3D AmlDeleteTree ((AML_NODE_HEADER*)RdNode); + ASSERT_EFI_ERROR (Status1); + // Return original error. + return Status; + } + } + + return EFI_SUCCESS; +} + +/** Code generation for the "Interrupt ()" ASL function. + + This function creates a Resource Data element corresponding to the + "Interrupt ()" ASL function and stores it in an AML Data Node. + + The Resource Data effectively created is an Extended Interrupt Resource + Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descripto= r" + for more information about Extended Interrupt Resource Data. + + This function allocates memory to create a data node. It is the caller's + responsibility to either: + - attach this node to an AML tree; + - delete this node. + + @param [in] ResourceConsumer The device consumes the specified inter= rupt + or produces it for use by a child devic= e. + @param [in] EdgeTriggered The interrupt is edge triggered or + level triggered. + @param [in] ActiveLow The interrupt is active-high or active-= low. + @param [in] Shared The interrupt can be shared with other + devices or not (Exclusive). + @param [in] IrqList Interrupt list. Must be non-NULL. + @param [in] IrqCount Interrupt count. Must be non-zero. + @param [in] ParentNode If not NULL, add the generated node + to the end of the variable list of + argument of the ParentNode, but + before the "End Tag" Resource Data. + Must be a BufferOpNode. + @param [out] NewRdNode If success, contains the generated node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenInterrupt ( + IN BOOLEAN ResourceConsumer, + IN BOOLEAN EdgeTriggered, + IN BOOLEAN ActiveLow, + IN BOOLEAN Shared, + IN UINT32 * IrqList, + IN UINT8 IrqCount, + IN AML_OBJECT_NODE * ParentNode, OPTIONAL + OUT AML_DATA_NODE ** NewRdNode OPTIONAL + ) +{ + EFI_STATUS Status; + + AML_DATA_NODE * RdNode; + EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR RdInterrupt; + UINT32 * FirstInterrupt; + + if ((IrqList =3D=3D NULL) || + (IrqCount =3D=3D 0) || + ((ParentNode =3D=3D NULL) && (NewRdNode =3D=3D NULL))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + RdInterrupt.Header.Header.Bits.Name =3D + ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME; + RdInterrupt.Header.Header.Bits.Type =3D ACPI_LARGE_ITEM_FLAG; + RdInterrupt.Header.Length =3D sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRI= PTOR) - + sizeof (ACPI_LARGE_RESOURCE_HEADER); + RdInterrupt.InterruptVectorFlags =3D (ResourceConsumer ? BIT0 : 0) | + (EdgeTriggered ? BIT1 : 0) | + (ActiveLow ? BIT2 : 0) | + (Shared ? BIT3 : 0); + RdInterrupt.InterruptTableLength =3D IrqCount; + + // Get the address of the first interrupt field. + FirstInterrupt =3D RdInterrupt.InterruptNumber; + + // Copy the list of interrupts. + CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount)); + + Status =3D AmlCreateDataNode ( + EAmlNodeDataTypeResourceData, + (UINT8*)&RdInterrupt, + sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR), + &RdNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + return LinkRdNode (RdNode, ParentNode, NewRdNode); +} + +/** Add an Interrupt Resource Data node. + + This function creates a Resource Data element corresponding to the + "Interrupt ()" ASL function, stores it in an AML Data Node. + + It then adds it after the input CurrRdNode in the list of resource data + element. + + The Resource Data effectively created is an Extended Interrupt Resource + Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descripto= r" + for more information about Extended Interrupt Resource Data. + + The Extended Interrupt contains one single interrupt. + + This function allocates memory to create a data node. It is the caller's + responsibility to either: + - attach this node to an AML tree; + - delete this node. + + Note: The _CRS node must be defined using the ASL Name () function. + e.g. Name (_CRS, ResourceTemplate () { + ... + } + + @param [in] NameOpCrsNode NameOp object node defining a "_CRS" obje= ct. + Must have an OpCode=3DAML_NAME_OP, SubOpC= ode=3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] ResourceConsumer The device consumes the specified interru= pt + or produces it for use by a child device. + @param [in] EdgeTriggered The interrupt is edge triggered or + level triggered. + @param [in] ActiveLow The interrupt is active-high or active-lo= w. + @param [in] Shared The interrupt can be shared with other + devices or not (Exclusive). + @param [in] IrqList Interrupt list. Must be non-NULL. + @param [in] IrqCount Interrupt count. Must be non-zero. + + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenCrsAddRdInterrupt ( + IN AML_OBJECT_NODE_HANDLE NameOpCrsNode, + IN BOOLEAN ResourceConsumer, + IN BOOLEAN EdgeTriggered, + IN BOOLEAN ActiveLow, + IN BOOLEAN Shared, + IN UINT32 * IrqList, + IN UINT8 IrqCount + ) +{ + EFI_STATUS Status; + + AML_OBJECT_NODE_HANDLE BufferOpNode; + + if ((IrqList =3D=3D NULL) = || + (IrqCount =3D=3D 0) = || + (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) = || + (!AmlNameOpCompareName (NameOpCrsNode, "_CRS"))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the _CRS value which is represented as a BufferOp object node + // which is the 2nd fixed argument (i.e. index 1). + BufferOpNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + NameOpCrsNode, + EAmlParseIndexTerm1 + ); + if ((BufferOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) !=3D EAmlNodeObject)= || + (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Generate the Extended Interrupt Resource Data node, + // and attach it as the last variable argument of the BufferOpNode. + Status =3D AmlCodeGenInterrupt ( + ResourceConsumer, + EdgeTriggered, + ActiveLow, + Shared, + IrqList, + IrqCount, + BufferOpNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceData= CodeGen.h b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataC= odeGen.h new file mode 100644 index 0000000000000000000000000000000000000000..08364db4431f8d41c70f220ee74= 17453ceb2496d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen= .h @@ -0,0 +1,59 @@ +/** @file + AML Resource Data Code Generation. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_RESOURCE_DATA_CODE_GEN_H_ +#define AML_RESOURCE_DATA_CODE_GEN_H_ + +/** Code generation for the "Interrupt ()" ASL function. + + This function creates a Resource Data element corresponding to the + "Interrupt ()" ASL function and stores it in an AML Data Node. + + The Resource Data effectively created is an Extended Interrupt Resource + Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descripto= r" + for more information about Extended Interrupt Resource Data. + + This function allocates memory to create a data node. It is the caller's + responsibility to either: + - attach this node to an AML tree; + - delete this node. + + @param [in] ResourceConsumer The device consumes the specified inter= rupt + or produces it for use by a child devic= e. + @param [in] EdgeTriggered The interrupt is edge triggered or + level triggered. + @param [in] ActiveLow The interrupt is active-high or active-= low. + @param [in] Shared The interrupt can be shared with other + devices or not (Exclusive). + @param [in] IrqList Interrupt list. Must be non-NULL. + @param [in] IrqCount Interrupt count. Must be non-zero. + @param [in] ParentNode If not NULL, add the generated node + to the end of the variable list of + argument of the ParentNode, but + before the "End Tag" Resource Data. + Must be a BufferOpNode. + @param [out] NewRdNode If success, contains the generated node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenInterrupt ( + IN BOOLEAN ResourceConsumer, + IN BOOLEAN EdgeTriggered, + IN BOOLEAN ActiveLow, + IN BOOLEAN Shared, + IN UINT32 * IrqList, + IN UINT8 IrqCount, + IN AML_OBJECT_NODE * ParentNode, OPTIONAL + OUT AML_DATA_NODE ** NewRdNode OPTIONAL + ); + +#endif // AML_RESOURCE_DATA_CODE_GEN_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64104): https://edk2.groups.io/g/devel/message/64104 Mute This Topic: https://groups.io/mt/76149189/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64099+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245841808266.7241630592754; Wed, 12 Aug 2020 08:24:01 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 0ayDYY1788612x6OLh1WEYnb; Wed, 12 Aug 2020 08:24:01 -0700 X-Received: from EUR05-VI1-obe.outbound.protection.outlook.com (EUR05-VI1-obe.outbound.protection.outlook.com [40.107.21.52]) by mx.groups.io with SMTP id smtpd.web10.17205.1597245832052600315 for ; Wed, 12 Aug 2020 08:23:52 -0700 X-Received: from AM0PR06CA0088.eurprd06.prod.outlook.com (2603:10a6:208:fa::29) by DB6PR0801MB1686.eurprd08.prod.outlook.com (2603:10a6:4:3b::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.19; Wed, 12 Aug 2020 15:23:48 +0000 X-Received: from AM5EUR03FT007.eop-EUR03.prod.protection.outlook.com (2603:10a6:208:fa:cafe::5b) by AM0PR06CA0088.outlook.office365.com (2603:10a6:208:fa::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:48 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64099+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT007.mail.protection.outlook.com (10.152.16.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:48 +0000 X-Received: ("Tessian outbound bac899b43a54:v64"); Wed, 12 Aug 2020 15:23:48 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 7c723d2e6ba050ef X-CR-MTA-TID: 64aa7808 X-Received: from 170ed717c660.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 54C7F309-C496-4021-9E5A-D74C4EF34D28.1; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 170ed717c660.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:42 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=c6uY0rldUibZRT+Q/SS3ykxCMSFDofpLOpzjatIFy7AHjUhdvvnn79Jc6LwTbNgdXoKrpkS1lLusQECmrHOtaCHmlDf6MrxJ8wZ+L8hVsFxTtB76c4VBrCbchazpwPxC5MNe4qUyfp+z5GrL0DonIO9PCo/bKKiqiIH4VNgV6PrTcBoYK/LoOybJRQbHFkiIlyPIkKkDl/QOFwazgh6s9u+5RpahXK/QBtQ2v5JRG4OilOkVXrlWjR4qXH1/LZr1l0p7qMpWEN1SW/sHFVIk5vEGhUg9cGhjYqjCA3lQCzWuzBvHOAN1FfNO2zGKdQaarTpOInkDH8F4oNCekdVgjA== 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-SenderADCheck; bh=29pV7thJbUxPoAkG3V6m9MdVDuYUQn2zs8Mv/5DoBCE=; b=KgXQsGsEx8GlQqyt0i80yx2uEDIM5rHlBgFEyOm8SwWMXewUN6c2pXhpUqqKWit5ulo9f2DJgHXWsN78XxB7GESZd3qb7wG0CoBTe8XobRc7xzAWZsdzutsT5T7ZEAJxrV0WyYcWu6LVT8lM6ygD+QrpYAWkGIvCXazq3Lyi3sJF/lFVMTuUwqEr6cZC1nVWVUr/pW311rWML+PZKBMTXDrgHaPbpf7kJ9oqfYpMjQ6W5Y7ZvH27Y1fKkTo9EDecRI0JoAWItWQcI0Oi7acfI0B/Y+HsfthayKiVVwuW+JpGFTgnCHw2gQ/oNUJtIykI3SkhqYIPhYl8lthxDHk2Vw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0062.eurprd07.prod.outlook.com (2603:10a6:6:2a::24) by DB7PR08MB3226.eurprd08.prod.outlook.com (2603:10a6:5:22::26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16; Wed, 12 Aug 2020 15:23:41 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::12) by DB6PR07CA0062.outlook.office365.com (2603:10a6:6:2a::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.7 via Frontend Transport; Wed, 12 Aug 2020 15:23:40 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:40 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:37 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:37 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 23/30] DynamicTablesPkg: AML Core interface Date: Wed, 12 Aug 2020 16:22:29 +0100 Message-ID: <20200812152236.31164-24-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bdac413e-529a-486d-39d3-08d83ed3b5d3 X-MS-TrafficTypeDiagnostic: DB7PR08MB3226:|DB6PR0801MB1686: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2399;OLM:2399; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(136003)(39860400002)(396003)(346002)(376002)(46966005)(356005)(82310400002)(30864003)(82740400003)(81166007)(7696005)(2906002)(70586007)(8676002)(336012)(70206006)(44832011)(6666004)(47076004)(316002)(54906003)(6916009)(1076003)(8936002)(186003)(426003)(478600001)(83380400001)(2616005)(26005)(5660300002)(4326008)(86362001)(36756003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3226 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT007.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 770fd2e6-ce4c-4bd6-d58f-08d83ed3b17c X-Microsoft-Antispam-Message-Info: /ZUBiLnA58ySt3/+09p52ghEZls534LVGpcaF8yNYA+I54yQNOyd+nT9aSKKnHokRvZPKzKUMAofnHh8DPR1r+7GSHG97HK04SLrZWFMfZW315G8Mq/lxvCVCeKFKwy0xfay3c8muXscLsiRsPynNlXh1zJO8CvoxddNB9ZWPoxEx/yvmK6LYJVavy4XDN2MQbby7mlunGNe9Ksem1lnSLAa0fJoFkuTNY89iFaLwXelTcS5+3Cd3DrjF00igFErUfFmvZ5GWsGUuCWQGuX4p3MUSxHEaFdaiGSYK8FPu9fP7oQ+BwibOpHtrvdlBzQiEPDjdFsUb7j47PjtWF1gNPkC5CsrvYZl26msWHQac4L2taI6Y0sHXXvGlEt+9gNMkVYhojyt4JKZRMBskGn7Fw== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:48.1656 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bdac413e-529a-486d-39d3-08d83ed3b5d3 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: AM5EUR03FT007.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1686 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: QqQH7ojReekcczsnKllLXv5Wx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245841; bh=2wJKG9HcbzO2iSQhryGlfCLHzxIBlrhH1LcwBiVc0J8=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=iuKAuYf8jFDx3MMqIcT4J/7cZIi0IjPVGM1b9A7WacFFSY+i82k7dYML5CzvN165wsH txRwrAHvxE8GnutxOaKYKEYVDqcfN1vL3oTvlHeLlM8z/JE0CQcWpMiew3odwj4MpNWc3 Dm9bkTYp0ITn1nThlCuX2p45u7ESP0eGJnc= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AML Core interface APIs are internal APIs of the AmlLib library. These APIs can be used to: - Create/Delete/Clone an AML tree/node - Get/update Fixed and Variable arguments - Serialize an AML tree. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h | 767 ++++++++++= ++++++++++ 1 file changed, 767 insertions(+) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h b/Dy= namicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..9905cfe551b50eccb3576ff9bdb= 6a1b582199601 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h @@ -0,0 +1,767 @@ +/** @file + AML Core Interface. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_CORE_INTERFACE_H_ +#define AML_CORE_INTERFACE_H_ + +/* This header file does not include internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions + must be included by the caller file. The function prototypes must + only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node + definitions. + This allows to keep the functions defined here both internal and + potentially external. If necessary, any function of this file can + be exposed externally. + The Api folder is internal to the AmlLib, but should only use these + functions. They provide a "safe" way to interact with the AmlLib. +*/ + +#include +#include +#include + +/** + @defgroup CoreApis Core APIs + @ingroup AMLLib + @{ + Core APIs are the main APIs of the library. They allow to: + - Create an AML tree; + - Delete an AML tree; + - Clone an AML tree/node; + - Serialize an AML tree (convert the tree to a DSDT/SSDT table). + @} +*/ + +/** Serialize a tree to create a DSDT/SSDT table. + + If: + - the content of BufferSize is >=3D to the size needed to serialize the + definition block; + - Buffer is not NULL; + first serialize the ACPI DSDT/SSDT header from the root node, + then serialize the AML blob from the rest of the tree. + + The content of BufferSize is always updated to the size needed to + serialize the definition block. + + @ingroup CoreApis + + @param [in] RootNode Pointer to a root node. + @param [in] Buffer Buffer to write the DSDT/SSDT table to. + If Buffer is NULL, the size needed to + serialize the DSDT/SSDT table is returned + in BufferSize. + @param [in, out] BufferSize Pointer holding the size of the Buffer. + Its content is always updated to the size + needed to serialize the DSDT/SSDT table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. +**/ +EFI_STATUS +EFIAPI +AmlSerializeTree ( + IN AML_ROOT_NODE_HANDLE RootNode, + IN UINT8 * Buffer, OPTIONAL + IN OUT UINT32 * BufferSize + ); + +/** Clone a node. + + This function does not clone the children nodes. + The cloned node returned is not attached to any tree. + + @ingroup CoreApis + + @param [in] Node Pointer to a node. + @param [out] ClonedNode Pointer holding the cloned node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCloneNode ( + IN AML_NODE_HANDLE Node, + OUT AML_NODE_HANDLE * ClonedNode + ); + +/** + @defgroup TreeModificationApis Tree modification APIs + @ingroup AMLLib + @{ + Tree modification APIs allow to add/remove/replace nodes that are in a + variable list of arguments. + + No interface is provided to add/remove/replace nodes that are in a fix= ed + list of arguments. Indeed, these nodes are the spine of the tree and a + mismanipulation would make the tree inconsistent. + + It is however possible to modify the content of fixed argument nodes v= ia + @ref NodeInterfaceApis APIs. + @} +*/ + +/** Remove the Node from its parent's variable list of arguments. + + The function will fail if the Node is in its parent's fixed + argument list. + The Node is not deleted. The deletion is done separately + from the removal. + + @ingroup TreeModificationApis + + @param [in] Node Pointer to a Node. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlRemoveNodeFromVarArgList ( + IN AML_NODE_HANDLE Node + ); + +/** Add the NewNode to the head of the variable list of arguments + of the ParentNode. + + @ingroup TreeModificationApis + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddHead ( + IN AML_NODE_HANDLE ParentNode, + IN AML_NODE_HANDLE NewNode + ); + +/** Add the NewNode to the tail of the variable list of arguments + of the ParentNode. + + @ingroup TreeModificationApis + + @param [in] ParentNode Pointer to the parent node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddTail ( + IN AML_NODE_HANDLE ParentNode, + IN AML_NODE_HANDLE NewNode + ); + +/** Add the NewNode before the Node in the list of variable + arguments of the Node's parent. + + @ingroup TreeModificationApis + + @param [in] Node Pointer to a node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddBefore ( + IN AML_NODE_HANDLE Node, + IN AML_NODE_HANDLE NewNode + ); + +/** Add the NewNode after the Node in the variable list of arguments + of the Node's parent. + + @ingroup TreeModificationApis + + @param [in] Node Pointer to a node. + Must be a root or an object node. + @param [in] NewNode Pointer to the node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlVarListAddAfter ( + IN AML_NODE_HANDLE Node, + IN AML_NODE_HANDLE NewNode + ); + +/** Append a Resource Data node to the BufferOpNode. + + The Resource Data node is added at the end of the variable + list of arguments of the BufferOpNode, but before the End Tag. + If no End Tag is found, the function returns an error. + + @param [in] BufferOpNode Buffer node containing resource data element= s. + @param [in] NewRdNode The new Resource Data node to add. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlAppendRdNode ( + IN AML_OBJECT_NODE_HANDLE BufferOpNode, + IN AML_DATA_NODE_HANDLE NewRdNode + ); + +/** Replace the OldNode, which is in a variable list of arguments, + with the NewNode. + + Note: This function unlinks the OldNode from the tree. It is the callers + responsibility to delete the OldNode if needed. + + @ingroup TreeModificationApis + + @param [in] OldNode Pointer to the node to replace. + Must be a data node or an object node. + @param [in] NewNode The new node to insert. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlReplaceVariableArgument ( + IN AML_NODE_HANDLE OldNode, + IN AML_NODE_HANDLE NewNode + ); + +/** + @defgroup NodeInterfaceApis Node Interface APIs + @ingroup AMLLib + @{ + Node Interface APIs allow to query information from a node. Some funct= ions + expect a specific node type among the root/object/data node types. + + For instance, AmlGetRootNodeInfo expects to receive a root node. + + E.g.: Query the node type, the ACPI header stored in the root node, + the OpCode/SubOpCode/PkgLen of an object node, the type of data + stored in a data node, etc. + + These APIs also allow to update some information. + + E.g.: The ACPI header stored in the root node, the buffer of a data no= de. + + The information of object nodes and the data type of data nodes cannot= be + modified. This prevents the creation of an inconsistent tree. + + It is however possible to remove a node from a variable list of argume= nts + and replace it. Use the @ref TreeModificationApis APIs for this. + @} +*/ + +/** Returns the tree node type (Root/Object/Data). + + @ingroup NodeInterfaceApis + + @param [in] Node Pointer to a Node. + + @return The node type. + EAmlNodeUnknown if invalid parameter. +**/ +EAML_NODE_TYPE +EFIAPI +AmlGetNodeType ( + IN AML_NODE_HANDLE Node + ); + +/** Get the RootNode information. + The Node must be a root node. + + @ingroup NodeInterfaceApis + + @param [in] RootNode Pointer to a root node. + @param [out] SdtHeaderBuffer Buffer to copy the ACPI DSDT/SSDT header= to. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetRootNodeInfo ( + IN AML_ROOT_NODE_HANDLE RootNode, + OUT EFI_ACPI_DESCRIPTION_HEADER * SdtHeaderBuffer + ); + +/** Get the ObjectNode information. + The Node must be an object node. + + @ingroup NodeInterfaceApis + + @param [in] ObjectNode Pointer to an object node. + @param [out] OpCode Pointer holding the OpCode. + Optional, can be NULL. + @param [out] SubOpCode Pointer holding the SubOpCode. + Optional, can be NULL. + @param [out] PkgLen Pointer holding the PkgLen. + The PkgLen is 0 for nodes + not having the Pkglen attribute. + Optional, can be NULL. + @param [out] IsNameSpaceNode Pointer holding TRUE if the node is defi= ning + or changing the NameSpace scope. + E.g.: The "Name ()" and "Scope ()" ASL + statements add/modify the NameSpace scop= e. + Their corresponding node are NameSpace n= odes. + Optional, can be NULL. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetObjectNodeInfo ( + IN AML_OBJECT_NODE_HANDLE ObjectNode, + OUT UINT8 * OpCode, OPTIONAL + OUT UINT8 * SubOpCode, OPTIONAL + OUT UINT32 * PkgLen, OPTIONAL + OUT BOOLEAN * IsNameSpaceNode OPTIONAL + ); + +/** Returns the count of the fixed arguments for the input Node. + + @ingroup NodeInterfaceApis + + @param [in] Node Pointer to an object node. + + @return Number of fixed arguments of the object node. + Return 0 if the node is not an object node. +**/ +UINT8 +AmlGetFixedArgumentCount ( + IN AML_OBJECT_NODE_HANDLE Node + ); + +/** Get the data type of the DataNode. + The Node must be a data node. + + @ingroup NodeInterfaceApis + + @param [in] DataNode Pointer to a data node. + @param [out] DataType Pointer holding the data type of the data buffer. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetNodeDataType ( + IN AML_DATA_NODE_HANDLE DataNode, + OUT EAML_NODE_DATA_TYPE * DataType + ); + +/** Get the descriptor Id of the resource data element + contained in the DataNode. + + The Node must be a data node. + The Node must have the resource data type, i.e. have the + EAmlNodeDataTypeResourceData data type. + + @ingroup NodeInterfaceApis + + @param [in] DataNode Pointer to a data node containing a + resource data element. + @param [out] ResourceDataType Pointer holding the descriptor Id of + the resource data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetResourceDataType ( + IN AML_DATA_NODE_HANDLE DataNode, + OUT AML_RD_HEADER * ResourceDataType + ); + +/** Get the data buffer and size of the DataNode. + The Node must be a data node. + + BufferSize is always updated to the size of buffer of the DataNode. + + If: + - the content of BufferSize is >=3D to the DataNode's buffer size; + - Buffer is not NULL; + then copy the content of the DataNode's buffer in Buffer. + + @ingroup NodeInterfaceApis + + @param [in] DataNode Pointer to a data node. + @param [out] Buffer Buffer to write the data to. + Optional, if NULL, only update BufferSiz= e. + @param [in, out] BufferSize Pointer holding: + - At entry, the size of the Buffer; + - At exit, the size of the DataNode's + buffer size. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlGetDataNodeBuffer ( + IN AML_DATA_NODE_HANDLE DataNode, + OUT UINT8 * Buffer, OPTIONAL + IN OUT UINT32 * BufferSize + ); + +/** Update the ACPI DSDT/SSDT table header. + + The input SdtHeader information is copied to the tree RootNode. + The table Length field is automatically updated. + The checksum field is only updated when serializing the tree. + + @ingroup NodeInterfaceApis + + @param [in] RootNode Pointer to a root node. + @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT table header. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRootNode ( + IN AML_ROOT_NODE_HANDLE RootNode, + IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader + ); + +/** Update an object node representing an integer with a new value. + + The object node must have one of the following OpCodes: + - AML_BYTE_PREFIX + - AML_WORD_PREFIX + - AML_DWORD_PREFIX + - AML_QWORD_PREFIX + - AML_ZERO_OP + - AML_ONE_OP + + The following OpCode is not supported: + - AML_ONES_OP + + @param [in] IntegerOpNode Pointer an object node containing an intege= r. + Must not be an object node with an AML_ONES= _OP + OpCode. + @param [in] NewInteger New integer value to set. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateInteger ( + IN AML_OBJECT_NODE_HANDLE IntegerOpNode, + IN UINT64 NewInteger + ); + +/** Update the buffer of a data node. + + Note: The data type of the buffer's content must match the data type of = the + DataNode. This is a hard restriction to prevent undesired behaviou= r. + + @ingroup NodeInterfaceApis + + @param [in] DataNode Pointer to a data node. + @param [in] DataType Data type of the Buffer's content. + @param [in] Buffer Buffer containing the new data. The content of + the Buffer is copied. + @param [in] Size Size of the Buffer. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_UNSUPPORTED Operation not supporter. +**/ +EFI_STATUS +EFIAPI +AmlUpdateDataNode ( + IN AML_DATA_NODE_HANDLE DataNode, + IN EAML_NODE_DATA_TYPE DataType, + IN UINT8 * Buffer, + IN UINT32 Size + ); + +/** + @defgroup NavigationApis Navigation APIs + @ingroup AMLLib + @{ + Navigation APIs allow to navigate in the AML tree. There are different + ways to navigate in the tree by: + - Direct relation (@ref CoreNavigationApis); + - Enumeration: enumerate all the nodes and call a callback function + (@ref EnumerationApis); + - Iteration: instantiate an iterator and use it to navigate + (@ref IteratorApis); + - NameSpace path: use the AML namespace to navigate the tree + (@ref NameSpaceApis). + @} +*/ + +/** + @defgroup CoreNavigationApis Core Navigation APIs + @ingroup NavigationApis + @{ + Core Navigation APIs allow to get a node by specifying a relation. + + E.g.: Get the parent, the n-th fixed argument, the next variable + argument, etc. + @} +*/ + +/** Get the parent node of the input Node. + + @ingroup CoreNavigationApis + + @param [in] Node Pointer to a node. + + @return The parent node of the input Node. + NULL otherwise. +**/ +AML_NODE_HANDLE +EFIAPI +AmlGetParent ( + IN AML_NODE_HANDLE Node + ); + +/** Get the node at the input Index in the fixed argument list of the input + ObjectNode. + + @ingroup CoreNavigationApis + + @param [in] ObjectNode Pointer to an object node. + @param [in] Index The Index of the fixed argument to get. + + @return The node at the input Index in the fixed argument list + of the input ObjectNode. + NULL otherwise, e.g. if the node is not an object node, or no + node is available at this Index. +**/ +AML_NODE_HANDLE +EFIAPI +AmlGetFixedArgument ( + IN AML_OBJECT_NODE_HANDLE ObjectNode, + IN EAML_PARSE_INDEX Index + ); + +/** Get the sibling node among the nodes being in + the same variable argument list. + + (ParentNode) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(VarArgNode)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Node must be in a variable list of arguments. + Traversal Order: VarArgNode, f, g, NULL + + @ingroup CoreNavigationApis + + @param [in] VarArgNode Pointer to a node. + Must be in a variable list of arguments. + + @return The next node after VarArgNode in the variable list of arguments. + Return NULL if + - VarArgNode is the last node of the list, or + - VarArgNode is not part of a variable list of arguments. +**/ +AML_NODE_HANDLE +EFIAPI +AmlGetSiblingVariableArgument ( + IN AML_NODE_HANDLE VarArgNode + ); + +/** Get the next variable argument. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: e, f, g, NULL + + @ingroup CoreNavigationApis + + @param [in] Node Pointer to a Root node or Object Node. + @param [in] CurrVarArg Pointer to the Current Variable Argument. + + @return The node after the CurrVarArg in the variable list of arguments. + If CurrVarArg is NULL, return the first node of the + variable argument list. + Return NULL if + - CurrVarArg is the last node of the list, or + - Node does not have a variable list of arguments. +**/ +AML_NODE_HANDLE +EFIAPI +AmlGetNextVariableArgument ( + IN AML_NODE_HANDLE Node, + IN AML_NODE_HANDLE CurrVarArg + ); + +/** Get the previous variable argument. + + (Node) /-i # Child of fixed argument b + \ / + |- [a][b][c][d] # Fixed Arguments + |- {(e)->(f)->(g)} # Variable Arguments + \ + \-h # Child of variable argument e + + Traversal Order: g, f, e, NULL + + @ingroup CoreNavigationApis + + @param [in] Node Pointer to a root node or an object node. + @param [in] CurrVarArg Pointer to the Current Variable Argument. + + @return The node before the CurrVarArg in the variable list of + arguments. + If CurrVarArg is NULL, return the last node of the + variable list of arguments. + Return NULL if: + - CurrVarArg is the first node of the list, or + - Node doesn't have a variable list of arguments. +**/ +AML_NODE_HANDLE +EFIAPI +AmlGetPreviousVariableArgument ( + IN AML_NODE_HANDLE Node, + IN AML_NODE_HANDLE CurrVarArg + ); + +/** + @defgroup EnumerationApis Enumeration APIs + @ingroup NavigationApis + @{ + Enumeration APIs are navigation APIs, allowing to call a callback func= tion + on each node enumerated. Nodes are enumerated in the AML bytestream or= der, + i.e. in a depth first order. + @} +*/ + +/** + Callback function prototype used when iterating through the tree. + + @ingroup EnumerationApis + + @param [in] Node The Node currently being processed. + @param [in, out] Context A context for the callback function. + Can be optional. + @param [in, out] Status End the enumeration if pointing to a value + evaluated to TRUE. + Can be optional. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +typedef +BOOLEAN +(EFIAPI * EDKII_AML_TREE_ENUM_CALLBACK) ( + IN AML_NODE_HANDLE Node, + IN OUT VOID * Context, OPTIONAL + IN OUT EFI_STATUS * Status OPTIONAL + ); + +/** Enumerate all nodes of the subtree under the input Node in the AML + bytestream order (i.e. in a depth first order), and call the CallBack + function with the input Context. + The prototype of the Callback function is EDKII_AML_TREE_ENUM_CALLBACK. + + @ingroup EnumerationApis + + @param [in] Node Enumerate nodes of the subtree under this No= de. + Must be a valid node. + @param [in] CallBack Callback function to call on each node. + @param [in, out] Context Void pointer used to pass some information + to the Callback function. + Optional, can be NULL. + @param [out] Status Optional parameter that can be used to get + the status of the Callback function. + If used, need to be init to EFI_SUCCESS. + + @retval TRUE if the enumeration can continue or has finished without + interruption. + @retval FALSE if the enumeration needs to stopped or has stopped. +**/ +BOOLEAN +EFIAPI +AmlEnumTree ( + IN AML_NODE_HANDLE Node, + IN EDKII_AML_TREE_ENUM_CALLBACK CallBack, + IN OUT VOID * Context, OPTIONAL + OUT EFI_STATUS * Status OPTIONAL + ); + +/** + @defgroup NameSpaceApis NameSpace APIs + @ingroup NavigationApis + @{ + NameSpace APIs allow to find a node from an AML path, and reciprocally + get the AML path of a node. + + These APIs only operate on "NameSpace nodes", i.e. nodes that are + part of the AML namespace. These are the root node and object nodes + acknowledged by AmlGetObjectNodeInfo in @ref NodeInterfaceApis. + @} +*/ + +/** Build the absolute ASL pathname to Node. + + BufferSize is always updated to the size of the pathname. + + If: + - the content of BufferSize is >=3D to the size of the pathname AND; + - Buffer is not NULL; + then copy the pathname in the Buffer. A buffer of the size + MAX_ASL_NAMESTRING_SIZE is big enough to receive any ASL pathname. + + @ingroup NameSpaceApis + + @param [in] Node Node to build the absolute path to. + Must be a root node, or a namespace no= de. + @param [out] Buffer Buffer to write the path to. + If NULL, only update *BufferSize. + @param [in, out] BufferSize Pointer holding: + - At entry, the size of the Buffer; + - At exit, the size of the pathname. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlGetAslPathName ( + IN AML_NODE_HANDLE Node, + OUT CHAR8 * Buffer, + IN OUT UINT32 * BufferSize + ); + +#endif // AML_CORE_INTERFACE_H_ --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64099): https://edk2.groups.io/g/devel/message/64099 Mute This Topic: https://groups.io/mt/76149184/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64103+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245849534754.6285661267164; Wed, 12 Aug 2020 08:24:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id m1jiYY1788612xJgZZagN3jY; Wed, 12 Aug 2020 08:24:08 -0700 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com (EUR05-DB8-obe.outbound.protection.outlook.com [40.107.20.65]) by mx.groups.io with SMTP id smtpd.web12.16984.1597245834305695257 for ; Wed, 12 Aug 2020 08:23:54 -0700 X-Received: from AM6P193CA0124.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::29) by HE1PR0802MB2538.eurprd08.prod.outlook.com (2603:10a6:3:e1::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:85:cafe::6) by AM6P193CA0124.outlook.office365.com (2603:10a6:209:85::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64103+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT023.mail.protection.outlook.com (10.152.16.169) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +0000 X-Received: ("Tessian outbound 195a290eb161:v64"); Wed, 12 Aug 2020 15:23:49 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 8efa3f7f5850ac0e X-CR-MTA-TID: 64aa7808 X-Received: from 0a744d12b6d6.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 22C121D8-B975-442A-B154-65B350749D66.1; Wed, 12 Aug 2020 15:23:44 +0000 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 0a744d12b6d6.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:44 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=e+w+m6qExR9r+rMHdhSnabOsv87nfY0fGlaKfbu5YnQQh/fLDacJIsyeO26hnT5+dNNoQGiTHoxC6EN5yPDDsby0MhNXv24usP9rzWNR0adHa/I1ZkB9/45StuuUNwNZdQSPnaUgWIq/iBbtU6h7DKk3u/Oc0nUDrYS/I7truWGb8iSQFjvLRNfRTcB8oVkMm/vuPYoYBmF0rl/LrJV/kPQ2HV7q3IdLAcOzUPMWLIO0ImUL6TBXBuToU+b39jNo+65HfvDIlOjjlmLi2niXmMHAx8rwNM9sadDaCHXOpOysYH0JEn5eoBk743SbK8SY395rM0ZKaH+MMpDmUw7I/g== 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-SenderADCheck; bh=Au1UZhyONIm0A1c8SSuHnzy/w+9C5XvpxMuoqpGyQg8=; b=fLiFQrqYPTo93bax1HDmxzPGEdNu1Ea2PbP7HqnZdid0bhJKINThyIiuJuq2j3cb5LW7NLt3qLLQ1igQq5a/tki23W7Q+7TbHQTs1nIefHLdr3vtOnRJKVy15l0lxTmYHfvFH+e4byD6JfjStCgC0eCdoszmP8Y4vskR5ZwUo1Ao7H7aI7p0UZOkbaelJZ4dleccbStfG8CiiLh2lAOvUoDowkAsZTS2lyGDkdKvHFejzY3raVvF7RZuvuoDGLkrfuALAJpILxXJsEyzRULKv96VaNBDjQdyyq0QhJXeyeiMrDJqRdA241BDdPZJEGyNegrCfDp/TMmKXdPF1zm3YQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0062.eurprd07.prod.outlook.com (2603:10a6:6:2a::24) by PR3PR08MB5673.eurprd08.prod.outlook.com (2603:10a6:102:86::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:41 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::12) by DB6PR07CA0062.outlook.office365.com (2603:10a6:6:2a::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.7 via Frontend Transport; Wed, 12 Aug 2020 15:23:41 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:41 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:39 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:38 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 24/30] DynamicTablesPkg: AmlLib APIs Date: Wed, 12 Aug 2020 16:22:30 +0100 Message-ID: <20200812152236.31164-25-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 29ffc730-7f9c-47da-3b8f-08d83ed3b6d4 X-MS-TrafficTypeDiagnostic: PR3PR08MB5673:|HE1PR0802MB2538: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2000;OLM:2000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: d7xkJtq7wQMMukR2KjjwocD6Hjq0UccbulwZV8VLUwW8LmVi2rOeugPSS69AxUzVXUlhBFWM40k8z3HdUhCiuNvCBElX5P6M4fxT+R71lvcEZFU7ZYdBcMeJKpaJyMvduNA4J0MUEt3I4YYhFP6/zu3qUaywHARfH39UF+7QB+C/5iAKmcNQgxwyBnwp9CbxgD9gwsMWS07RidG4LW6dz5O7Vr4/stJIiyJ5A1f0xPvgWMhKhDioaQHn0/6h3j37LtA9QkSpmY6CY9Zegstqh1kGJuHBZkWdPNR846IIlEAzy7KazBCT5uFBrKWxBvUkfE7AzISt/OU8qSyTmIBLmkpGhUv1qJr7woiwu3DXCiSHoSLCKv6HoC2tWkOdXn4TpfHUk9pnzWP5nztM8A8y3g== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(396003)(136003)(376002)(39860400002)(346002)(46966005)(30864003)(6916009)(2906002)(1076003)(86362001)(54906003)(19627235002)(4326008)(8676002)(83380400001)(5660300002)(26005)(8936002)(336012)(316002)(7696005)(47076004)(82310400002)(70206006)(36756003)(70586007)(356005)(478600001)(44832011)(6666004)(82740400003)(186003)(81166007)(426003)(2616005)(579004)(559001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR3PR08MB5673 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 06f2cae2-ee0b-4285-eb2e-08d83ed3b1dc X-Microsoft-Antispam-Message-Info: bBw7OmnPqjHK3dU/VCunBH6XcjLFU5CzwesGjJ/pwUcx74yK2C5MoMtxTfgzDqLtTk/BtXW96ySqhxk2rjJFNqccD9Sj9z8PhJCgfHYW/bmUkjt3KOd/qDi/S3I4jwcPS/uvq+nkCdpxS4xDG5B/0jD48GlxepvSLZPNu2Q7TV5J2OtIiEAlQdVDkSRj7+0hFoZ5fgYurxnFOaihECLegF1xeoyhpti6r7KCfgjDi/hSLSOKnhTDsWoyO1eO/ef4cazat1cjippEa6p5Co6W7/fqbm8MjiBN4AaGIvRP4gG4pue0NzYpCWdx71GNYWutVrhQMAz0oJbhk9KlPqBfmrK65GQSrl1ph3JIFuO58sn4jPybSkIRLHZF5aMqnpb0B1LHOXCHT2gkIQQM7rhbyg== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:49.8559 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 29ffc730-7f9c-47da-3b8f-08d83ed3b6d4 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: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0802MB2538 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: x7XJ2MMh6a2Z0Q1XGdg4mEo9x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245848; bh=sgFGIgdXRmoBUCSOEbMy9hrdYX2tWKaaffUzjleN7rk=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=BnbZxa/Uaq8QGRpc6twxi5DfKbyeFxGfJodGghnHUFG1eoOMV6Zj7kyCHKx6B5rF39A oZeuMyJHMULX4LAL9PrSKRqrlI4v4vYJeMxTdVHqXMCLx9ELoMAQqkidxJ4g6kJZ0MlJM xTP/9OBHLU2elkeRjHvg9QmRal8xKoGNzVs= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois AmlLib library implements an AML parser, AML tree interface, serialiser, code generator and other interfaces to generate Definition Block tables. The AmlLib APIs are a collection of interfaces that enable parsing, iterating, modifying, adding, and serialising AML data to generate a Definition Block table. The AmlLib APIs are declared in Include\AmlLib\AmlLib.h Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h | 631 ++++= ++++++++++++++++ DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c | 382 ++++= ++++++++ DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c | 219 ++++= +++ DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h | 93 +++ DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c | 320 ++++= ++++++ 5 files changed, 1645 insertions(+) diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTabl= esPkg/Include/Library/AmlLib/AmlLib.h new file mode 100644 index 0000000000000000000000000000000000000000..1dcb93861436851e848f9cb5fd6= 9621ccd7bf7a1 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -0,0 +1,631 @@ +/** @file + AML Lib. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_LIB_H_ +#define AML_LIB_H_ + +/** + @mainpage Dynamic AML Generation + @{ + @par Summary + @{ + ACPI tables are categorized as data tables and definition block + tables. Dynamic Tables Framework currently supports generation of ACPI + data tables. Generation of definition block tables is difficult as the= se + tables are encoded in ACPI Machine Language (AML), which has a complex + grammar. + + Dynamic AML Generation is an extension to the Dynamic tables Framework. + One of the techniques used to simplify definition block generation is = to + fixup a template SSDT table. + + Dynamic AML aims to provide a framework that allows fixing up of an AC= PI + SSDT template with appropriate information about the hardware. + + This framework consists of an: + - AMLLib core that implements a rich set of interfaces to parse, trave= rse + and update AML data. + - AMLLib library APIs that provides interfaces to search and updates n= odes + in the AML namespace. + @} + @} +*/ + +#include + +#ifndef AML_HANDLE + +/** Node handle. +*/ +typedef void* AML_NODE_HANDLE; + +/** Root Node handle. +*/ +typedef void* AML_ROOT_NODE_HANDLE; + +/** Object Node handle. +*/ +typedef void* AML_OBJECT_NODE_HANDLE; + +/** Data Node handle. +*/ +typedef void* AML_DATA_NODE_HANDLE; + +#endif // AML_HANDLE + +/** Parse the definition block. + + The function parses the whole AML blob. It starts with the ACPI DSDT/SSDT + header and then parses the AML bytestream. + A tree structure is returned via the RootPtr. + The tree must be deleted with the AmlDeleteTree function. + + @ingroup UserApis + + @param [in] DefinitionBlock Pointer to the definition block. + @param [out] RootPtr Pointer to the root node of the AML tree. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlParseDefinitionBlock ( + IN CONST EFI_ACPI_DESCRIPTION_HEADER * DefinitionBlock, + OUT AML_ROOT_NODE_HANDLE * RootPtr + ); + +/** Serialize an AML definition block. + + This functions allocates memory with the "AllocateZeroPool ()" + function. This memory is used to serialize the AML tree and is + returned in the Table. + + @ingroup UserApis + + @param [in] RootNode Root node of the tree. + @param [out] Table On return, hold the serialized + definition block. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlSerializeDefinitionBlock ( + IN AML_ROOT_NODE_HANDLE RootNode, + OUT EFI_ACPI_DESCRIPTION_HEADER ** Table + ); + +/** Clone a node and its children (clone a tree branch). + + The cloned branch returned is not attached to any tree. + + @ingroup UserApis + + @param [in] Node Pointer to a node. + Node is the head of the branch to clone. + @param [out] ClonedNode Pointer holding the head of the created cloned + branch. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCloneTree ( + IN AML_NODE_HANDLE Node, + OUT AML_NODE_HANDLE * ClonedNode + ); + +/** Delete a Node and its children. + + The Node must be removed from the tree first, + or must be the root node. + + @ingroup UserApis + + @param [in] Node Pointer to the node to delete. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeleteTree ( + IN AML_NODE_HANDLE Node + ); + +/** Detach the Node from the tree. + + The function will fail if the Node is in its parent's fixed + argument list. + The Node is not deleted. The deletion is done separately + from the removal. + + @ingroup UserApis + + @param [in] Node Pointer to a Node. + Must be a data node or an object node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDetachNode ( + IN AML_NODE_HANDLE Node + ); + +/** Find a node in the AML namespace, given an ASL path and a reference No= de. + + - The AslPath can be an absolute path, or a relative path from the + reference Node; + - Node must be a root node or a namespace node; + - A root node is expected to be at the top of the tree. + + E.g.: + For the following AML namespace, with the ReferenceNode being the node w= ith + the name "AAAA": + - the node with the name "BBBB" can be found by looking for the ASL + path "BBBB"; + - the root node can be found by looking for the ASL relative path "^", + or the absolute path "\\". + + AML namespace: + \ + \-AAAA <- ReferenceNode + \-BBBB + + @ingroup NameSpaceApis + + @param [in] ReferenceNode Reference node. + If a relative path is given, the + search is done from this node. If + an absolute path is given, the + search is done from the root node. + Must be a root node or an object + node which is part of the + namespace. + @param [in] AslPath ASL path to the searched node in + the namespace. An ASL path name is + NULL terminated. Can be a relative + or absolute path. + E.g.: "\\_SB.CLU0.CPU0" or "^CPU0" + @param [out] OutNode Pointer to the found node. + Contains NULL if not found. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_BUFFER_TOO_SMALL No space left in the buffer. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +EFIAPI +AmlFindNode ( + IN AML_NODE_HANDLE ReferenceNode, + IN CHAR8 * AslPath, + OUT AML_NODE_HANDLE * OutNode + ); + +/** + @defgroup UserApis User APIs + @{ + User APIs are implemented to ease most common actions that might be do= ne + using the AmlLib. They allow to find specific objects like "_UID" or + "_CRS" and to update their value. It also shows what can be done using + AmlLib functions. + @} +*/ + +/** Update the name of a DeviceOp object node. + + @ingroup UserApis + + @param [in] DeviceOpNode Object node representing a Device. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + OpCode/SubOpCode. + DeviceOp object nodes are defined in ASL + using the "Device ()" function. + @param [in] NewNameString The new Device's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeviceOpUpdateName ( + IN AML_OBJECT_NODE_HANDLE DeviceOpNode, + IN CHAR8 * NewNameString + ); + +/** Update an integer value defined by a NameOp object node. + + For compatibility reasons, the NameOpNode must initially + contain an integer. + + @ingroup UserApis + + @param [in] NameOpNode NameOp object node. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] NewInt New Integer value to assign. + Must be a UINT64. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpUpdateInteger ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN UINT64 NewInt + ); + +/** Update a string value defined by a NameOp object node. + + The NameOpNode must initially contain a string. + The EISAID ASL macro converts a string to an integer. This, it is + not accepted. + + @ingroup UserApis + + @param [in] NameOpNode NameOp object node. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] NewName New NULL terminated string to assign to + the NameOpNode. + The input string is copied. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpUpdateString ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN CONST CHAR8 * NewName + ); + +/** Get the first Resource Data element contained in a "_CRS" object. + + In the following ASL code, the function will return the Resource Data + node corresponding to the "QWordMemory ()" ASL macro. + Name (_CRS, ResourceTemplate() { + QWordMemory (...) {...}, + Interrupt (...) {...} + } + ) + + Note: + - The "_CRS" object must be declared using ASL "Name (Declare Named Obj= ect)". + - "_CRS" declared using ASL "Method (Declare Control Method)" is not + supported. + + @ingroup UserApis + + @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [out] OutRdNode Pointer to the first Resource Data element of + the "_CRS" object. A Resource Data element + is stored in a data node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpCrsGetFirstRdNode ( + IN AML_OBJECT_NODE_HANDLE NameOpCrsNode, + OUT AML_DATA_NODE_HANDLE * OutRdNode + ); + +/** Get the Resource Data element following the CurrRdNode Resource Data. + + In the following ASL code, if CurrRdNode corresponds to the first + "QWordMemory ()" ASL macro, the function will return the Resource Data + node corresponding to the "Interrupt ()" ASL macro. + Name (_CRS, ResourceTemplate() { + QwordMemory (...) {...}, + Interrupt (...) {...} + } + ) + + The CurrRdNode Resource Data node must be defined in an object named "_C= RS" + and defined by a "Name ()" ASL function. + + @ingroup UserApis + + @param [in] CurrRdNode Pointer to the current Resource Data element = of + the "_CRS" variable. + @param [out] OutRdNode Pointer to the Resource Data element following + the CurrRdNode. + Contain a NULL pointer if CurrRdNode is the + last Resource Data element in the list. + The "End Tag" is not considered as a resource + data element and is not returned. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpCrsGetNextRdNode ( + IN AML_DATA_NODE_HANDLE CurrRdNode, + OUT AML_DATA_NODE_HANDLE * OutRdNode + ); + +/** Update the first interrupt of an Interrupt resource data node. + + The flags of the Interrupt resource data are left unchanged. + + The InterruptRdNode corresponds to the Resource Data created by the + "Interrupt ()" ASL macro. It is an Extended Interrupt Resource Data. + See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor" + for more information about Extended Interrupt Resource Data. + + @ingroup UserApis + + @param [in] InterruptRdNode Pointer to the an extended interrupt + resource data node. + @param [in] Irq Interrupt value to update. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRdInterrupt ( + IN AML_DATA_NODE_HANDLE InterruptRdNode, + IN UINT32 Irq + ); + +/** Update the base address and length of a QWord resource data node. + + @ingroup UserApis + + @param [in] QWordRdNode Pointer a QWord resource data + node. + @param [in] BaseAddress Base address. + @param [in] BaseAddressLength Base address length. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRdQWord ( + IN AML_DATA_NODE_HANDLE QWordRdNode, + IN UINT64 BaseAddress, + IN UINT64 BaseAddressLength + ); + +/** Add an Interrupt Resource Data node. + + This function creates a Resource Data element corresponding to the + "Interrupt ()" ASL function, stores it in an AML Data Node. + + It then adds it after the input CurrRdNode in the list of resource data + element. + + The Resource Data effectively created is an Extended Interrupt Resource + Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descripto= r" + for more information about Extended Interrupt Resource Data. + + The Extended Interrupt contains one single interrupt. + + This function allocates memory to create a data node. It is the caller's + responsibility to either: + - attach this node to an AML tree; + - delete this node. + + Note: The _CRS node must be defined using the ASL Name () function. + e.g. Name (_CRS, ResourceTemplate () { + ... + } + + @ingroup UserApis + + @param [in] NameOpCrsNode NameOp object node defining a "_CRS" obje= ct. + Must have an OpCode=3DAML_NAME_OP, SubOpC= ode=3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] ResourceConsumer The device consumes the specified interru= pt + or produces it for use by a child device. + @param [in] EdgeTriggered The interrupt is edge triggered or + level triggered. + @param [in] ActiveLow The interrupt is active-high or active-lo= w. + @param [in] Shared The interrupt can be shared with other + devices or not (Exclusive). + @param [in] IrqList Interrupt list. Must be non-NULL. + @param [in] IrqCount Interrupt count. Must be non-zero. + + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenCrsAddRdInterrupt ( + IN AML_OBJECT_NODE_HANDLE NameOpCrsNode, + IN BOOLEAN ResourceConsumer, + IN BOOLEAN EdgeTriggered, + IN BOOLEAN ActiveLow, + IN BOOLEAN Shared, + IN UINT32 * IrqList, + IN UINT8 IrqCount + ); + +/** AML code generation for DefinitionBlock. + + Create a Root Node handle. + It is the caller's responsibility to free the allocated memory + with the AmlDeleteTree function. + + AmlCodeGenDefinitionBlock (TableSignature, OemId, TableID, OEMRevision) = is + equivalent to the following ASL code: + DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision, + OemId, TableID, OEMRevision) {} + with the ComplianceRevision set to 2 and the AMLFileName is ignored. + + @ingroup CodeGenApis + + @param[in] TableSignature 4-character ACPI signature. + Must be 'DSDT' or 'SSDT'. + @param[in] OemId 6-character string OEM identifier. + @param[in] OemTableId 8-character string OEM table identifier. + @param[in] OemRevision OEM revision number. + @param[out] DefinitionBlockTerm The ASL Term handle representing a + Definition Block. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCodeGenDefinitionBlock ( + IN CONST CHAR8 * TableSignature, + IN CONST CHAR8 * OemId, + IN CONST CHAR8 * OemTableId, + IN UINT32 OemRevision, + OUT AML_ROOT_NODE_HANDLE * NewRootNode + ); + +/** AML code generation for a Name object node, containing a String. + + AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Name(_HID, "HID0000") + + @ingroup CodeGenApis + + @param [in] NameString The new variable name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @param [in] String NULL terminated String to associate to the + NameString. + @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 +AmlCodeGenNameString ( + IN CONST CHAR8 * NameString, + IN CHAR8 * String, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ); + +/** AML code generation for a Name object node, containing an Integer. + + AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Name(_UID, One) + + @ingroup CodeGenApis + + @param [in] NameString The new variable name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @param [in] Integer Integer to associate to the NameString. + @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 +AmlCodeGenNameInteger ( + IN CONST CHAR8 * NameString, + IN UINT64 Integer, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ); + +/** AML code generation for a Device object node. + + AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Device(COM0) {} + + @ingroup CodeGenApis + + @param [in] NameString The new Device's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @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 +AmlCodeGenDevice ( + IN CONST CHAR8 * NameString, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ); + +/** AML code generation for a Scope object node. + + AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is + equivalent of the following ASL code: + Scope(_SB) {} + + @ingroup CodeGenApis + + @param [in] NameString The new Scope's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + @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 +AmlCodeGenScope ( + IN CONST CHAR8 * NameString, + IN AML_NODE_HANDLE ParentNode, OPTIONAL + OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL + ); + +#endif // AML_LIB_H_ diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c b/DynamicT= ablesPkg/Library/Common/AmlLib/Api/AmlApi.c new file mode 100644 index 0000000000000000000000000000000000000000..fdf04acc6212f9d6b6f691f30a6= 0fea6f0b43e6f --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c @@ -0,0 +1,382 @@ +/** @file + AML Api. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +/* Even though this file has access to the internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node + handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, + etc. + Indeed, the functions in the "Api" folder should be implemented only + using the "safe" functions available in the "Include" folder. This + makes the functions available in the "Api" folder easy to export. +*/ +#include + +#include +#include +#include +#include + +/** Update the name of a DeviceOp object node. + + @param [in] DeviceOpNode Object node representing a Device. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + OpCode/SubOpCode. + DeviceOp object nodes are defined in ASL + using the "Device ()" function. + @param [in] NewNameString The new Device's name. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + The input string is copied. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlDeviceOpUpdateName ( + IN AML_OBJECT_NODE_HANDLE DeviceOpNode, + IN CHAR8 * NewNameString + ) +{ + EFI_STATUS Status; + + AML_DATA_NODE_HANDLE DeviceNameDataNode; + CHAR8 * NewAmlNameString; + UINT32 NewAmlNameStringSize; + + // Check the input node is an object node. + if ((DeviceOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)DeviceOpNode) !=3D EAmlNodeObject)= || + (!AmlNodeHasOpCode (DeviceOpNode, AML_EXT_OP, AML_EXT_DEVICE_OP)) = || + (NewNameString =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the Device's name, being a data node + // which is the 1st fixed argument (i.e. index 0). + DeviceNameDataNode =3D (AML_DATA_NODE_HANDLE)AmlGetFixedArgument ( + DeviceOpNode, + EAmlParseIndexTerm0 + ); + if ((DeviceNameDataNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)DeviceNameDataNode) !=3D EAmlNodeD= ata) || + (!AmlNodeHasDataType (DeviceNameDataNode, EAmlNodeDataTypeNameString= ))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status =3D ConvertAslNameToAmlName (NewNameString, &NewAmlNameString); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status =3D AmlGetNameStringSize (NewAmlNameString, &NewAmlNameStringSize= ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Update the Device's name node. + Status =3D AmlUpdateDataNode ( + DeviceNameDataNode, + EAmlNodeDataTypeNameString, + (UINT8*)NewAmlNameString, + NewAmlNameStringSize + ); + ASSERT_EFI_ERROR (Status); + +exit_handler: + FreePool (NewAmlNameString); + return Status; +} + +/** Update an integer value defined by a NameOp object node. + + For compatibility reasons, the NameOpNode must initially + contain an integer. + + @param [in] NameOpNode NameOp object node. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] NewInt New Integer value to assign. + Must be a UINT64. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpUpdateInteger ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN UINT64 NewInt + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE IntegerOpNode; + + if ((NameOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) !=3D EAmlNodeObject) || + (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the Integer object node defined by the "Name ()" function: + // it must have an Integer OpCode (Byte/Word/DWord/QWord). + // It is the 2nd fixed argument (i.e. index 1) of the NameOp node. + // This can also be a ZeroOp or OneOp node. + IntegerOpNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + NameOpNode, + EAmlParseIndexTerm1 + ); + if ((IntegerOpNode =3D=3D NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)IntegerOpNode) !=3D EAmlNodeObject= )) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update the Integer value. + Status =3D AmlUpdateInteger (IntegerOpNode, NewInt); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Update a string value defined by a NameOp object node. + + The NameOpNode must initially contain a string. + The EISAID ASL macro converts a string to an integer. This, it is + not accepted. + + @param [in] NameOpNode NameOp object node. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] NewName New NULL terminated string to assign to + the NameOpNode. + The input string is copied. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpUpdateString ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN CONST CHAR8 * NewName + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE StringOpNode; + AML_DATA_NODE_HANDLE StringDataNode; + + if ((NameOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) !=3D EAmlNodeObject) || + (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the String object node defined by the "Name ()" function: + // it must have a string OpCode. + // It is the 2nd fixed argument (i.e. index 1) of the NameOp node. + StringOpNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + NameOpNode, + EAmlParseIndexTerm1 + ); + if ((StringOpNode =3D=3D NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)StringOpNode) !=3D EAmlNodeObject)= ) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the string data node. + // It is the 1st fixed argument (i.e. index 0) of the StringOpNode node. + StringDataNode =3D (AML_DATA_NODE_HANDLE)AmlGetFixedArgument ( + StringOpNode, + EAmlParseIndexTerm0 + ); + if ((StringDataNode =3D=3D NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)StringDataNode) !=3D EAmlNodeData)= ) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Update the string value. + Status =3D AmlUpdateDataNode ( + StringDataNode, + EAmlNodeDataTypeString, + (UINT8*)NewName, + (UINT32)AsciiStrLen (NewName) + 1 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Get the first Resource Data element contained in a "_CRS" object. + + In the following ASL code, the function will return the Resource Data + node corresponding to the "QWordMemory ()" ASL macro. + Name (_CRS, ResourceTemplate() { + QWordMemory (...) {...}, + Interrupt (...) {...} + } + ) + + Note: + - The "_CRS" object must be declared using ASL "Name (Declare Named Obj= ect)". + - "_CRS" declared using ASL "Method (Declare Control Method)" is not + supported. + + @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object. + Must have an OpCode=3DAML_NAME_OP, SubOpCode= =3D0. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [out] OutRdNode Pointer to the first Resource Data element of + the "_CRS" object. A Resource Data element + is stored in a data node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpCrsGetFirstRdNode ( + IN AML_OBJECT_NODE_HANDLE NameOpCrsNode, + OUT AML_DATA_NODE_HANDLE * OutRdNode + ) +{ + AML_OBJECT_NODE_HANDLE BufferOpNode; + AML_DATA_NODE_HANDLE FirstRdNode; + + if ((NameOpCrsNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)NameOpCrsNode) !=3D EAmlNodeObject= ) || + (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) = || + (!AmlNameOpCompareName (NameOpCrsNode, "_CRS")) = || + (OutRdNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutRdNode =3D NULL; + + // Get the _CRS value which is represented as a BufferOp object node + // which is the 2nd fixed argument (i.e. index 1). + BufferOpNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + NameOpCrsNode, + EAmlParseIndexTerm1 + ); + if ((BufferOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) !=3D EAmlNodeObject)= || + (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the first Resource data node in the variable list of + // argument of the BufferOp node. + FirstRdNode =3D (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument ( + (AML_NODE_HANDLE)BufferOpNode, + NULL + ); + if ((FirstRdNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)FirstRdNode) !=3D EAmlNodeData) || + (!AmlNodeHasDataType (FirstRdNode, EAmlNodeDataTypeResourceData))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutRdNode =3D FirstRdNode; + return EFI_SUCCESS; +} + +/** Get the Resource Data element following the CurrRdNode Resource Data. + + In the following ASL code, if CurrRdNode corresponds to the first + "QWordMemory ()" ASL macro, the function will return the Resource Data + node corresponding to the "Interrupt ()" ASL macro. + Name (_CRS, ResourceTemplate() { + QwordMemory (...) {...}, + Interrupt (...) {...} + } + ) + + The CurrRdNode Resource Data node must be defined in an object named "_C= RS" + and defined by a "Name ()" ASL function. + + @param [in] CurrRdNode Pointer to the current Resource Data element = of + the "_CRS" object. + @param [out] OutRdNode Pointer to the Resource Data element following + the CurrRdNode. + Contain a NULL pointer if CurrRdNode is the + last Resource Data element in the list. + The "End Tag" is not considered as a resource + data element and is not returned. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlNameOpCrsGetNextRdNode ( + IN AML_DATA_NODE_HANDLE CurrRdNode, + OUT AML_DATA_NODE_HANDLE * OutRdNode + ) +{ + AML_OBJECT_NODE_HANDLE NameOpCrsNode; + AML_OBJECT_NODE_HANDLE BufferOpNode; + + if ((CurrRdNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)CurrRdNode) !=3D EAmlNodeData) = || + (!AmlNodeHasDataType (CurrRdNode, EAmlNodeDataTypeResourceData)) || + (OutRdNode =3D=3D NULL)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutRdNode =3D NULL; + + // The parent of the CurrRdNode must be a BufferOp node. + BufferOpNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetParent ( + (AML_NODE_HANDLE)CurrRdNode + ); + if ((BufferOpNode =3D=3D NULL) || + (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // The parent of the BufferOpNode must be a NameOp node. + NameOpCrsNode =3D (AML_OBJECT_NODE_HANDLE)AmlGetParent ( + (AML_NODE_HANDLE)BufferOpNode + ); + if ((NameOpCrsNode =3D=3D NULL) || + (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) || + (!AmlNameOpCompareName (NameOpCrsNode, "_CRS"))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + *OutRdNode =3D (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument ( + (AML_NODE_HANDLE)BufferOpNode, + (AML_NODE_HANDLE)CurrRdNode + ); + + // If the Resource Data is an End Tag, return NULL. + if (AmlNodeHasRdDataType ( + *OutRdNode, + AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) { + *OutRdNode =3D NULL; + } + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c b/Dy= namicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c new file mode 100644 index 0000000000000000000000000000000000000000..9693f28b543f2008d17d09031ed= 3b53577935a5d --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c @@ -0,0 +1,219 @@ +/** @file + AML Helper. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +/* Even though this file has access to the internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node + handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, + etc. + Indeed, the functions in the "Api" folder should be implemented only + using the "safe" functions available in the "Include" folder. This + makes the functions available in the "Api" folder easy to export. +*/ +#include + +#include +#include +#include + +/** Compare the NameString defined by the "Name ()" ASL function, + and stored in the NameOpNode, with the input NameString. + + An ASL NameString is expected to be NULL terminated, and can be composed + of NameSegs that have less that 4 chars, like "DEV". "DEV" will be expan= ded + as "DEV_". + + An AML NameString is not NULL terminated and is is only composed of + 4 chars long NameSegs. + + @param [in] NameOpNode NameOp object node defining a variable. + Must have an AML_NAME_OP/0 OpCode/SubOpCode. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] AslName ASL NameString to compare the NameOp's name wi= th. + Must be NULL terminated. + + @retval TRUE If the AslName and the AmlName defined by the NameOp node + are similar. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNameOpCompareName ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN CHAR8 * AslName + ) +{ + EFI_STATUS Status; + AML_DATA_NODE_HANDLE NameDataNode; + + CHAR8 * AmlName; + UINT32 AmlNameSize; + + BOOLEAN RetVal; + + if ((NameOpNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) !=3D EAmlNodeObject) = || + (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)) = || + (AslName =3D=3D NULL)) { + ASSERT (0); + return FALSE; + } + + // Get the NameOp name, being in a data node + // which is the first fixed argument (i.e. index 0). + NameDataNode =3D (AML_DATA_NODE_HANDLE)AmlGetFixedArgument ( + NameOpNode, + EAmlParseIndexTerm0 + ); + if ((NameDataNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)NameDataNode) !=3D EAmlNodeData) = || + (!AmlNodeHasDataType (NameDataNode, EAmlNodeDataTypeNameString))) { + ASSERT (0); + return FALSE; + } + + // Get the size of the name. + Status =3D AmlGetDataNodeBuffer (NameDataNode, NULL, &AmlNameSize); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // Allocate memory to fetch the name. + AmlName =3D AllocateZeroPool (AmlNameSize); + if (AmlName =3D=3D NULL) { + ASSERT (0); + return FALSE; + } + + // Fetch the name. + Status =3D AmlGetDataNodeBuffer (NameDataNode, (UINT8*)AmlName, &AmlName= Size); + if (EFI_ERROR (Status)) { + FreePool (AmlName); + ASSERT (0); + return FALSE; + } + + // Compare the input AslName and the AmlName stored in the NameOp node. + RetVal =3D CompareAmlWithAslNameString (AmlName, AslName); + + // Free the string buffer. + FreePool (AmlName); + return RetVal; +} + +/** Check whether ObjectNode has the input OpCode/SubOpcode couple. + + @param [in] ObjectNode Pointer to an object node. + @param [in] OpCode OpCode to check + @param [in] SubOpCode SubOpCode to check + + @retval TRUE The node is an object node and + the Opcode and SubOpCode match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasOpCode ( + IN AML_OBJECT_NODE_HANDLE ObjectNode, + IN UINT8 OpCode, + IN UINT8 SubOpCode + ) +{ + EFI_STATUS Status; + UINT8 NodeOpCode; + UINT8 NodeSubOpCode; + + // Get the Node information. + Status =3D AmlGetObjectNodeInfo ( + ObjectNode, + &NodeOpCode, + &NodeSubOpCode, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // Check the OpCode and SubOpCode. + if ((OpCode !=3D NodeOpCode) || + (SubOpCode !=3D NodeSubOpCode)) { + return FALSE; + } + + return TRUE; +} + +/** Check whether DataNode has the input DataType. + + @param [in] DataNode Pointer to a data node. + @param [in] DataType DataType to check. + + @retval TRUE The node is a data node and + the DataType match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasDataType ( + IN AML_DATA_NODE_HANDLE DataNode, + IN EAML_NODE_DATA_TYPE DataType + ) +{ + EFI_STATUS Status; + EAML_NODE_DATA_TYPE NodeDataType; + + // Get the data type. + Status =3D AmlGetNodeDataType (DataNode, &NodeDataType); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // Check the data type. + if (NodeDataType !=3D DataType) { + return FALSE; + } + + return TRUE; +} + +/** Check whether RdNode has the input RdDataType. + + @param [in] RdNode Pointer to a data node. + @param [in] RdDataType DataType to check. + + @retval TRUE The node is a Resource Data node and + the RdDataType match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasRdDataType ( + IN AML_DATA_NODE_HANDLE RdNode, + IN AML_RD_HEADER RdDataType + ) +{ + EFI_STATUS Status; + AML_RD_HEADER NodeRdDataType; + + // Get the resource data type. + Status =3D AmlGetResourceDataType ( + RdNode, + &NodeRdDataType + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return FALSE; + } + + // Check the RdDataType. + return AmlRdCompareDescId (&NodeRdDataType, RdDataType); +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h b/Dy= namicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..9872adddc36739559c862685644= 83480a6d65294 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h @@ -0,0 +1,93 @@ +/** @file + AML Helper. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef AML_HELPER_H_ +#define AML_HELPER_H_ + +#include +#include + +/** Compare the NameString defined by the "Name ()" ASL function, + and stored in the NameOpNode, with the input NameString. + + An ASL NameString is expected to be NULL terminated, and can be composed + of NameSegs that have less that 4 chars, like "DEV". "DEV" will be expan= ded + as "DEV_". + + An AML NameString is not NULL terminated and is is only composed of + 4 chars long NameSegs. + + @param [in] NameOpNode NameOp object node defining a variable. + Must have an AML_NAME_OP/0 OpCode/SubOpCode. + NameOp object nodes are defined in ASL + using the "Name ()" function. + @param [in] AslName ASL NameString to compare the NameOp's name wi= th. + Must be NULL terminated. + + @retval TRUE If the AslName and the AmlName defined by the NameOp node + are similar. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNameOpCompareName ( + IN AML_OBJECT_NODE_HANDLE NameOpNode, + IN CHAR8 * AslName + ); + +/** Check whether ObjectNode has the input OpCode/SubOpcode couple. + + @param [in] ObjectNode Pointer to an object node. + @param [in] OpCode OpCode to check + @param [in] SubOpCode SubOpCode to check + + @retval TRUE The node is an object node and + the Opcode and SubOpCode match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasOpCode ( + IN AML_OBJECT_NODE_HANDLE ObjectNode, + IN UINT8 OpCode, + IN UINT8 SubOpCode + ); + +/** Check whether DataNode has the input DataType. + + @param [in] DataNode Pointer to a data node. + @param [in] DataType DataType to check. + + @retval TRUE The node is a data node and + the DataType match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasDataType ( + IN AML_DATA_NODE_HANDLE DataNode, + IN EAML_NODE_DATA_TYPE DataType + ); + +/** Check whether RdNode has the input RdDataType. + + @param [in] RdNode Pointer to a data node. + @param [in] RdDataType DataType to check. + + @retval TRUE The node is a Resource Data node and + the RdDataType match. + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +AmlNodeHasRdDataType ( + IN AML_DATA_NODE_HANDLE RdNode, + IN AML_RD_HEADER RdDataType + ); + +#endif // AML_HELPER_H_ diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.= c b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c new file mode 100644 index 0000000000000000000000000000000000000000..913c8dcdb0c04d7180a0732cfc6= c5f495105f8e9 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c @@ -0,0 +1,320 @@ +/** @file + AML Update Resource Data. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +/* Even though this file has access to the internal Node definition, + i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node + handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, + etc. + Indeed, the functions in the "Api" folder should be implemented only + using the "safe" functions available in the "Include" folder. This + makes the functions available in the "Api" folder easy to export. +*/ +#include + +#include +#include +#include +#include + +/** Update the first interrupt of an Interrupt resource data node. + + The flags of the Interrupt resource data are left unchanged. + + The InterruptRdNode corresponds to the Resource Data created by the + "Interrupt ()" ASL macro. It is an Extended Interrupt Resource Data. + See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor" + for more information about Extended Interrupt Resource Data. + + @param [in] InterruptRdNode Pointer to the an extended interrupt + resource data node. + @param [in] Irq Interrupt value to update. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRdInterrupt ( + IN AML_DATA_NODE_HANDLE InterruptRdNode, + IN UINT32 Irq + ) +{ + EFI_STATUS Status; + UINT32 * FirstInterrupt; + UINT8 * QueryBuffer; + UINT32 QueryBufferSize; + + if ((InterruptRdNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)InterruptRdNode) !=3D EAmlNodeData= ) || + (!AmlNodeHasDataType ( + InterruptRdNode, + EAmlNodeDataTypeResourceData)) = || + (!AmlNodeHasRdDataType ( + InterruptRdNode, + AML_RD_BUILD_LARGE_DESC_ID ( + ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME)))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + QueryBuffer =3D NULL; + + // Get the size of the InterruptRdNode buffer. + Status =3D AmlGetDataNodeBuffer ( + InterruptRdNode, + NULL, + &QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Check the Buffer is large enough. + if (QueryBufferSize < sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Allocate a buffer to fetch the data. + QueryBuffer =3D AllocatePool (QueryBufferSize); + if (QueryBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Get the data. + Status =3D AmlGetDataNodeBuffer ( + InterruptRdNode, + QueryBuffer, + &QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + // Get the address of the first interrupt field. + FirstInterrupt =3D + ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)QueryBuffer)->InterruptNumbe= r; + + *FirstInterrupt =3D Irq; + + // Update the InterruptRdNode buffer. + Status =3D AmlUpdateDataNode ( + InterruptRdNode, + EAmlNodeDataTypeResourceData, + QueryBuffer, + QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + +error_handler: + if (QueryBuffer !=3D NULL) { + FreePool (QueryBuffer); + } + return Status; +} + +/** Update the interrupt list of an interrupt resource data node. + + The InterruptRdNode corresponds to the Resource Data created by the + "Interrupt ()" ASL function. It is an Extended Interrupt Resource Data. + See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor" + for more information about Extended Interrupt Resource Data. + + @param [in] InterruptRdNode Pointer to the an extended interrupt + resource data node. + @param [in] ResourceConsumer The device consumes the specified inte= rrupt + or produces it for use by a child devi= ce. + @param [in] EdgeTriggered The interrupt is edge triggered or + level triggered. + @param [in] ActiveLow The interrupt is active-high or active= -low. + @param [in] Shared The interrupt can be shared with other + devices or not (Exclusive). + @param [in] IrqList Interrupt list. Must be non-NULL. + @param [in] IrqCount Interrupt count. Must be non-zero. + + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRdInterruptEx ( + IN AML_DATA_NODE_HANDLE InterruptRdNode, + IN BOOLEAN ResourceConsumer, + IN BOOLEAN EdgeTriggered, + IN BOOLEAN ActiveLow, + IN BOOLEAN Shared, + IN UINT32 * IrqList, + IN UINT8 IrqCount + ) +{ + EFI_STATUS Status; + + EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR * RdInterrupt; + UINT32 * FirstInterrupt; + UINT8 * UpdateBuffer; + UINT16 UpdateBufferSize; + + if ((InterruptRdNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)InterruptRdNode) !=3D EAmlNodeData= ) || + (!AmlNodeHasDataType ( + InterruptRdNode, + EAmlNodeDataTypeResourceData)) = || + (!AmlNodeHasRdDataType ( + InterruptRdNode, + AML_RD_BUILD_LARGE_DESC_ID ( + ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME))) = || + (IrqList =3D=3D NULL) = || + (IrqCount =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + UpdateBuffer =3D NULL; + UpdateBufferSize =3D sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) + + ((IrqCount - 1) * sizeof (UINT32)); + + // Allocate a buffer to update the data. + UpdateBuffer =3D AllocatePool (UpdateBufferSize); + if (UpdateBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Update the Resource Data information (structure size, interrupt count= ). + RdInterrupt =3D (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)UpdateBuffer; + RdInterrupt->Header.Header.Byte =3D + AML_RD_BUILD_LARGE_DESC_ID (ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME); + RdInterrupt->Header.Length =3D + UpdateBufferSize - sizeof (ACPI_LARGE_RESOURCE_HEADER); + RdInterrupt->InterruptTableLength =3D IrqCount; + RdInterrupt->InterruptVectorFlags =3D (ResourceConsumer ? BIT0 : 0) | + (EdgeTriggered ? BIT1 : 0) | + (ActiveLow ? BIT2 : 0) | + (Shared ? BIT3 : 0); + + // Get the address of the first interrupt field. + FirstInterrupt =3D + ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)UpdateBuffer)->InterruptNumb= er; + + // Copy the input list of interrupts. + CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount)); + + // Update the InterruptRdNode buffer. + Status =3D AmlUpdateDataNode ( + InterruptRdNode, + EAmlNodeDataTypeResourceData, + UpdateBuffer, + UpdateBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + // Cleanup + FreePool (UpdateBuffer); + + return Status; +} + +/** Update the base address and length of a QWord resource data node. + + @param [in] QWordRdNode Pointer a QWord resource data + node. + @param [in] BaseAddress Base address. + @param [in] BaseAddressLength Base address length. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +EFIAPI +AmlUpdateRdQWord ( + IN AML_DATA_NODE_HANDLE QWordRdNode, + IN UINT64 BaseAddress, + IN UINT64 BaseAddressLength + ) +{ + EFI_STATUS Status; + EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR * RdQWord; + + UINT8 * QueryBuffer; + UINT32 QueryBufferSize; + + if ((QWordRdNode =3D=3D NULL) = || + (AmlGetNodeType ((AML_NODE_HANDLE)QWordRdNode) !=3D EAmlNodeData) = || + (!AmlNodeHasDataType (QWordRdNode, EAmlNodeDataTypeResourceData)) || + (!AmlNodeHasRdDataType ( + QWordRdNode, + AML_RD_BUILD_LARGE_DESC_ID ( + ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME)))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Get the size of the QWordRdNode's buffer. + Status =3D AmlGetDataNodeBuffer ( + QWordRdNode, + NULL, + &QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Allocate a buffer to fetch the data. + QueryBuffer =3D AllocatePool (QueryBufferSize); + if (QueryBuffer =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + // Get the data. + Status =3D AmlGetDataNodeBuffer ( + QWordRdNode, + QueryBuffer, + &QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + RdQWord =3D (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR*)QueryBuffer; + + // Update the Base Address and Length. + RdQWord->AddrRangeMin =3D BaseAddress; + RdQWord->AddrRangeMax =3D BaseAddress + BaseAddressLength - 1; + RdQWord->AddrLen =3D BaseAddressLength; + + // Update Base Address Resource Data node. + Status =3D AmlUpdateDataNode ( + QWordRdNode, + EAmlNodeDataTypeResourceData, + QueryBuffer, + QueryBufferSize + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + +error_handler: + if (QueryBuffer !=3D NULL) { + FreePool (QueryBuffer); + } + return Status; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64103): https://edk2.groups.io/g/devel/message/64103 Mute This Topic: https://groups.io/mt/76149188/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64101+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245842591800.2847731954321; Wed, 12 Aug 2020 08:24:02 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id MEf7YY1788612xdbwwiyHZ9G; Wed, 12 Aug 2020 08:24:02 -0700 X-Received: from EUR04-HE1-obe.outbound.protection.outlook.com (EUR04-HE1-obe.outbound.protection.outlook.com [40.107.7.50]) by mx.groups.io with SMTP id smtpd.web10.17207.1597245832805824019 for ; Wed, 12 Aug 2020 08:23:53 -0700 X-Received: from MR2P264CA0056.FRAP264.PROD.OUTLOOK.COM (2603:10a6:500:31::20) by VE1PR08MB5054.eurprd08.prod.outlook.com (2603:10a6:803:10d::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com (2603:10a6:500:31:cafe::69) by MR2P264CA0056.outlook.office365.com (2603:10a6:500:31::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64101+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT028.mail.protection.outlook.com (10.152.18.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:49 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 0e0a659e563a865d X-CR-MTA-TID: 64aa7808 X-Received: from f154c7f66504.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 58CD13BC-71DC-44C9-A740-BC7CD658CEDC.1; Wed, 12 Aug 2020 15:23:44 +0000 X-Received: from EUR03-AM5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id f154c7f66504.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:44 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YNWorIVZC5h/Ckg/atOf0W0iGSdTYWyLJm5mRffEDfBVYrge3Si6ENSD3bhqtSGY/IXp6LchRT7AVkKE9GS0dCepUQb0IKAzqIRgFxFwPj53p14nmFt2rhtSAJL+/PlZ9mjhO4Su+mJdvtKfXH0cPbjvsQ+2kEARGA6zvIBZeF91+0yaHdnnSLzX65WiJHEzSNL2oOSs2sDnYFg+vv5vV84emPtfQzAgMjsK0EcpFQyC0tSffWGNSp+Lheoe5qaMpQ+HsG+j49HyBoBD2ajISSRSyHa5wUQ2nr69oO+OyTetsPQgAiPkzkimW0uJAeOPZ55DCgWXF7JXuezHduAp/w== 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-SenderADCheck; bh=+jJWbHNqTv2BlSHRMXga5k5RbwlAF2C1m6L7x8Ag0Kk=; b=KNkN9+nY4vqcJ/X1uxjbUUcO9bJOaFwMD99PQ6PQC6MlEtIl2DoJt5ydPHGER5BvvwW/IEjlP3p8ZXq43Cb5HJdVr1/66H4lrR98R8rUBuwbe3zyjX+QBAdITrS2/em9+eSW/Ei2/W4szf/KAQH490v/dFei11TZwKR28MeKPBckg2CDI203CsOqdOC3BUNlqasKlnyRCloWia9AoMyek7Ts6JFNB3V7fXalDwT2sVDmsItaHPqE4IekhbU13WImafMTRr0gK2YaVCRib/MY51xYVZEOgrN3lP/9XmVAqrs/LM2Kii4DgarfDWnW/cRqsW46ofP0+Y3QskKUt5/V0Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from DB6PR07CA0061.eurprd07.prod.outlook.com (2603:10a6:6:2a::23) by VI1PR0802MB2399.eurprd08.prod.outlook.com (2603:10a6:800:bb::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from DB5EUR03FT059.eop-EUR03.prod.protection.outlook.com (2603:10a6:6:2a:cafe::2b) by DB6PR07CA0061.outlook.office365.com (2603:10a6:6:2a::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3305.10 via Frontend Transport; Wed, 12 Aug 2020 15:23:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by DB5EUR03FT059.mail.protection.outlook.com (10.152.21.175) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:41 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:40 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 25/30] DynamicTablesPkg: Dynamic AML: Add AmlLib library Date: Wed, 12 Aug 2020 16:22:31 +0100 Message-ID: <20200812152236.31164-26-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 1004d7af-a131-423a-1ef9-08d83ed3b6ca X-MS-TrafficTypeDiagnostic: VI1PR0802MB2399:|VE1PR08MB5054: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:7219;OLM:7219; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: h+D7ecW64mPe18by9L56lOpiHih1ONTjIxR5bd8kroOVGF9goSvvClaPOT6fDdUQ/QHu6R5rw/FQ9WR0x3Ymab+SCKiLlz84oO+2KeLc5uu/xqJ1G9y/cKTK5y+WJxI7uLUxVngg4z1zaCn64rNffK6S56DrwFQ4zP2PliXDpveGvLmRO+nU3ObgSWKjlaL6NhncTLzl8Ui04SYnJV6H2E6PKLONEBGd438iYyUmZBgz5StDrkY3lK2bXZDzU+qfXRqctvoqJmML790a+gs8PSoLcSV62Pskxht5D1JOYGlIbKgo8inUSM2feZSmzQ1CFHfNxwHFT2Wtky5pxRwFpSwgnY9nDWuqdNGbpu9plE2hu8cV9UD6pgpm0jnm9cHon0RY7JEAFhY8yMxEPxwvYw== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(346002)(39860400002)(136003)(396003)(376002)(46966005)(186003)(1076003)(8936002)(36756003)(2906002)(26005)(6916009)(82740400003)(83380400001)(6666004)(478600001)(8676002)(54906003)(86362001)(70586007)(70206006)(5660300002)(7696005)(356005)(4326008)(2616005)(82310400002)(316002)(47076004)(81166007)(426003)(336012)(44832011);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0802MB2399 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 599ef0b2-a7cd-495e-12d0-08d83ed3b28d X-Microsoft-Antispam-Message-Info: 5dZkQUnn5/OmzwULrmA0PaPduK5PvTAJDUTh+byQ5Xb/L0zyLRl+nVbxB82695P5rUnxXrYATf6JGHGcKpJ/w1Z4DzqjhFTJ6v1dmqIy69tpwAi0wL1oVb5nLXBAofSihS3i401WodruJynYg3KtQ2A3UXo2xvtZnu2PpHEMZb2eUwlct+B/Sw0kU+C0O6Fe9Fv5qJYosTDbISNGwjyZCnY5BCHGlKf+G1YWa8VWY/UBSxjttO92A6iVJatLeIOyGIXa2tyJgWXcC77snLb2+3UDwBzOItE4axcnyXv/d8ufZN09THb3Grrtjbt505d2kgEtsot8nhXoQ9eyAs4cK6cp5p4C5bwdneFHDPA2B7DpdMgEd85EunJrY+MkLnjEJ5/YyUZ9+ONvUMU7eAFd0g== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:49.7526 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1004d7af-a131-423a-1ef9-08d83ed3b6ca 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: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR08MB5054 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: HmBFeKlLa03L0PlXWRHWsGnix1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245842; bh=Xwb/spvpFSmr/j1CSZEsvM9Dh+BDkIxaGSYVBGHAKSg=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=txvFFF/qhwRl3SVPditskFqLgQv4OZ/pEQmaE/Xev/S2TdD5Sm49/8X2WMPJh37Z92s WAX8gmtVFy2XZW5xtYq4CrE5mManbmlpsDS6HbNlh3UD4csBAoiMdklFcRSZZ/Gb7tt2c uIHuiewAPeKyd70IB4ipN85yV0KBh73fpH4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois ACPI Definition blocks are implemented using AML which has a complex grammar making run-time generation of definition blocks difficult. Dynamic AML is a feature of Dynamic Tables framework that provides a solution for dynamic generation of ACPI Definition block tables. Since, AML bytecode represents complex AML grammar, an AmlLib library is introduced to assist parsing and traversing of the AML bytecode at run-time. The AmlLib library parses a definition block and represents it as an AML tree. The AML objects, methods and data are represented as tree nodes. Since the AML data is represented as tree nodes, it is possible to traverse the tree, locate a node and modify the node data. The tree can then be serialized to a buffer (that represents the definition block). This definition block containing the fixed-up AML code can then be installed as an ACPI Definition Block table. Dynamic AML introduces the following techniques: * AML Fixup * AML Codegen * AML Fixup + Codegen AML Fixup is a technique that involves compiling an ASL template file to generate AML bytecode. This template AML bytecode can be parsed at run-time and a fixup code can update the required fields in the AML template. AML Codegen employs generating small segments of AML code. AmlLib provides a rich set of APIs to operate on AML data for AML Fixup and Codegen. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/DynamicTables.dsc.inc | 1 + DynamicTablesPkg/DynamicTablesPkg.ci.yaml | 6 +- DynamicTablesPkg/DynamicTablesPkg.dec | 5 +- DynamicTablesPkg/DynamicTablesPkg.dsc | 3 +- DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf | 76 ++++++++++++++++++++ 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dyna= micTables.dsc.inc index bc03c09d6c0ebb2c6b1458d27e0bde00224e55cd..928529f797b49f2f0dd52508a9a= ad557f568719a 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -13,6 +13,7 @@ [BuildOptions] RELEASE_*_*_CC_FLAGS =3D -DMDEPKG_NDEBUG =20 [LibraryClasses.common] + AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelpe= rLib.inf =20 [Components.common] diff --git a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/DynamicTablesPkg/D= ynamicTablesPkg.ci.yaml index f39b8019461ea151f9b1cf4bc751604d6e044af2..5ee20357326f4b79444d63418f5= 6aae0b00508de 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml +++ b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml @@ -1,7 +1,7 @@ ## @file # CI configuration for DynamicTablesPkg # -# Copyright (c) 2020, ARM Limited. All rights reserved.
+# Copyright (c) 2020, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent ## { @@ -69,11 +69,15 @@ "IgnoreFiles": [], # use gitignore syntax to ignore erro= rs # in matching files "ExtendWords": [ + "EISAID", "CCIDX", "CCSIDR", "countof", "EOBJECT", + "invoc", "GTBLOCK", + "lgreater", + "lless", "MPIDR", "pytool", "Roadmap", diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/Dynam= icTablesPkg.dec index 6cb8a0b4f2c91b59e888951fda034bfdc56d95e1..57e6815fa159c5ce8d5cb0c9303= 75e7322bff211 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -1,7 +1,7 @@ ## @file # dec file for Dynamic Tables Framework. # -# Copyright (c) 2017 - 2020, ARM Limited. All rights reserved.
+# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -17,6 +17,9 @@ [Includes] Include =20 [LibraryClasses] + ## @libraryclass Defines a set of APIs for Dynamic AML generation. + AmlLib|Include/Library/AmlLib/AmlLib.h + ## @libraryclass Defines a set of helper methods. TableHelperLib|Include/Library/TableHelperLib.h =20 diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/Dynam= icTablesPkg.dsc index 5fb30a9315a75750a7d4c3e802c610a7991111c7..add6b192ad4187e2769b374ef68= f93a65a1af8b6 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -2,7 +2,7 @@ # Dsc file for Dynamic Tables Framework. # # Copyright (c) 2019, Linaro Limited. All rights reserved.
-# Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
+# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -36,6 +36,7 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64] PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf =20 [Components.common] + DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf =20 [BuildOptions] diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf b/DynamicTab= lesPkg/Library/Common/AmlLib/AmlLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..e2babef445d5ed7dbd2f6aefbe2= 6fa39df2b1ada --- /dev/null +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf @@ -0,0 +1,76 @@ +## @file +# AML Generation Library +# +# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D DynamicAmlLib + FILE_GUID =3D 23A6AFDA-F2A5-45EC-BEFF-420639D345B9 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D AmlLib + +[Sources] + AmlCoreInterface.h + AmlDefines.h + AmlInclude.h + AmlNodeDefines.h + AmlDbgPrint/AmlDbgPrint.c + AmlDbgPrint/AmlDbgPrint.h + AmlEncoding/Aml.c + AmlEncoding/Aml.h + Api/AmlApi.c + Api/AmlApiHelper.c + Api/AmlApiHelper.h + Api/AmlResourceDataApi.c + CodeGen/AmlCodeGen.c + CodeGen/AmlResourceDataCodeGen.c + CodeGen/AmlResourceDataCodeGen.h + NameSpace/AmlNameSpace.c + NameSpace/AmlNameSpace.h + Parser/AmlFieldListParser.c + Parser/AmlFieldListParser.h + Parser/AmlMethodParser.c + Parser/AmlMethodParser.h + Parser/AmlParser.c + Parser/AmlParser.h + Parser/AmlResourceDataParser.c + Parser/AmlResourceDataParser.h + ResourceData/AmlResourceData.c + ResourceData/AmlResourceData.h + Serialize/AmlSerialize.c + Stream/AmlStream.c + Stream/AmlStream.h + String/AmlString.c + String/AmlString.h + Tree/AmlClone.c + Tree/AmlTreeIterator.h + Tree/AmlNode.c + Tree/AmlNode.h + Tree/AmlNodeInterface.c + Tree/AmlTree.c + Tree/AmlTree.h + Tree/AmlTreeEnumerator.c + Tree/AmlTreeIterator.c + Tree/AmlTreeTraversal.c + Tree/AmlTreeTraversal.h + Utils/AmlUtility.c + Utils/AmlUtility.h + +[Packages] + MdePkg/MdePkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + +[BuildOptions] + *_*_*_CC_FLAGS =3D -DAML_HANDLE + +[Protocols] + +[Guids] --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64101): https://edk2.groups.io/g/devel/message/64101 Mute This Topic: https://groups.io/mt/76149186/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64100+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245840978279.1273258743281; Wed, 12 Aug 2020 08:24:00 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 7aA7YY1788612xACpZjObYAF; Wed, 12 Aug 2020 08:24:00 -0700 X-Received: from EUR02-AM5-obe.outbound.protection.outlook.com (EUR02-AM5-obe.outbound.protection.outlook.com [40.107.0.77]) by mx.groups.io with SMTP id smtpd.web12.16982.1597245832324658486 for ; Wed, 12 Aug 2020 08:23:52 -0700 X-Received: from MR2P264CA0159.FRAP264.PROD.OUTLOOK.COM (2603:10a6:501:1::22) by DB7PR08MB3817.eurprd08.prod.outlook.com (2603:10a6:10:77::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.17; Wed, 12 Aug 2020 15:23:49 +0000 X-Received: from VE1EUR03FT057.eop-EUR03.prod.protection.outlook.com (2603:10a6:501:1:cafe::ca) by MR2P264CA0159.outlook.office365.com (2603:10a6:501:1::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64100+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT057.mail.protection.outlook.com (10.152.19.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +0000 X-Received: ("Tessian outbound 7fc8f57bdedc:v64"); Wed, 12 Aug 2020 15:23:49 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: ddd696711c568be4 X-CR-MTA-TID: 64aa7808 X-Received: from 0a008541c073.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 74DFACFA-98F2-4C8B-A0BB-31DF37D8B93E.1; Wed, 12 Aug 2020 15:23:44 +0000 X-Received: from EUR04-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 0a008541c073.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:44 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bd4tPQCZiR9vLtKp9PUHaMEFp60HSZJk8487baAN7dImk/gaj/Xok6rMDHODyCEhUC7rvc9E75gSh3isVmnCX6wKgJ1EOIjbH+kDc784m/VYyOPy+RZRzLfRctOXDy3m6KHIUuU62QQbIS/ES8iypcEYhm8/Rd2yUHsFUHCwNNGtbWaifvlU9HEDnvdtnLmaz+p573zoNAs+bi3IKX0PJ0pIsXL35Mm+j9/YSEOlGx2Ehb3uPCtvclj+4wkquw/mNfpkXrY5FmV8yF0WqvOXIVFzaNRqyWVwEMPaTGUK59ky/cAu4MT347Ts7MzWpqNBq+Gn+/4xgbcxRebHLzGIVQ== 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-SenderADCheck; bh=umfjmn24x9CuTRjJwVb5Z+enYXLfgGYry9hpxrYKTvE=; b=Hzjw4mmMqKuGBtGvCgs+N3xs61TFqUGX+MG6C1acoHBgYtWJuWK5CBw7T44XljQXOc0Pda24/o6wOYZVT/kLStqI6h0oysKYWUkVpxO2SgPLogPBoKcOrUIDS42827t2CNPuThgFAAf2zsGf1zxvy009oteu6sQXkpWqlcs0IlcpayyLsxQHPddQCTqtd0U4FkhpJtYQOsP9InU9pwtCplQSeLC7HUzhsUL61WImViaVXNtRs7ffu4V+w9GArkPckiT1TcpWN9pZXn2hJCHm0K8hyr/fAFaAkt+krmIFtdUDqTFG6LlzhRwvywAj1b8R1twa2R42Usk7/XG27iJIvA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6PR10CA0089.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::30) by AM4PR0802MB2195.eurprd08.prod.outlook.com (2603:10a6:200:5d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::9a) by AM6PR10CA0089.outlook.office365.com (2603:10a6:209:8c::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:41 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:41 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 26/30] DynamicTablesPkg: Add AsciiFromHex helper function Date: Wed, 12 Aug 2020 16:22:32 +0100 Message-ID: <20200812152236.31164-27-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a3488f8e-2b49-4980-a1b8-08d83ed3b6a5 X-MS-TrafficTypeDiagnostic: AM4PR0802MB2195:|DB7PR08MB3817: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4303;OLM:4303; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(39860400002)(346002)(396003)(376002)(136003)(46966005)(6916009)(1076003)(186003)(4326008)(8936002)(426003)(44832011)(54906003)(316002)(2616005)(81166007)(83380400001)(70586007)(336012)(2906002)(6666004)(82310400002)(36756003)(47076004)(5660300002)(82740400003)(70206006)(8676002)(7696005)(26005)(86362001)(478600001)(356005);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0802MB2195 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT057.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: ba7bd9ad-a615-4a6d-bd02-08d83ed3b262 X-Microsoft-Antispam-Message-Info: FIcb5rgvRviZowH1UYK0AAjOXNNGDTopFYnIs02m+YaUkJxjRVz2lSOGgPzE+FFe+d3UbV0paM/LO+MvGS45d2j0RaGGz9/9A3uW2P4sonQxOY/ZFw1XbBlrrnfQ1y1MEziH/sjq8OlEunB+rM1HQ+KqzsKa49a7M9xLMDWPCejRw0CstBnLMqcdKOhY7S2xToKNSRfwqIGkaKbVcUmDuYSKVqbEPX8Cs2PdUFWYp21TdHNhBGmymss0IhDiLGrp44LjFw7JjO4pqhzk5L2bY+BjKDGgpxpAwhuVWkZ2/3+kiPW3vLP9Ms+I2pMllrmrVp0ATMxKx983XXPgaqNwnUDqeBroiS9U7z1i6OmrJp2dyHY2Ey8UmFENqeydEacDFIBW9ilTgz3jYH0dLgsdhw== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:49.5185 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a3488f8e-2b49-4980-a1b8-08d83ed3b6a5 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: VE1EUR03FT057.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3817 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 5cMvY71XCSXwuF5xYyIlfCoYx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245840; bh=0RFBS/xkFJs0w4Z0NyTb4pbf6cIoleLcTJrc3KizAsk=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=KzxY4iZl3NrgY3KoPls9DUV/l87+/dqxQIQaLXLbHLz9cCGHS8a9WG2PqDVXTnT4t8h 26OprLaLs5ftfbTvyjt2zsnQLtZMXVV/Rg94Z3HwMpoiwUfBP1ANHOrfYoGBfmrQjGk1P nrtk9bK9u35obcsU6Lq3iLFvg37EalPKXb8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" AsciiFromHex is a function converts a hex number to an ASCII character. This function is used across multiple generators, so add it to the TableHelperLib. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Include/Library/TableHelperLib.h | 15 ++++++++= +- DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c | 30 ++++++++= ++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/DynamicTablesPkg/Include/Library/TableHelperLib.h b/DynamicTab= lesPkg/Include/Library/TableHelperLib.h index e4a8dfa046bd97d89f0297ccad521f317bed5c36..099a0a4544e3d1f746d4be8533c= b006786f11611 100644 --- a/DynamicTablesPkg/Include/Library/TableHelperLib.h +++ b/DynamicTablesPkg/Include/Library/TableHelperLib.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -107,4 +107,17 @@ FindDuplicateValue ( IN PFN_IS_EQUAL EqualTestFunction ); =20 +/** Convert a hex number to its ASCII code. + + @param [in] x Hex number to convert. + Must be 0 <=3D x < 16. + + @return The ASCII code corresponding to x. +**/ +UINT8 +EFIAPI +AsciiFromHex ( + IN UINT8 x + ); + #endif // TABLE_HELPER_LIB_H_ diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c b= /DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c index fc6cf3b088da1f7ad89dd4356b414bede9e80575..0d9daad3b05b6e82089f92afb6d= e4eeee5af9a28 100644 --- a/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c @@ -1,8 +1,9 @@ /** @file Table Helper =20 -Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. -SPDX-License-Identifier: BSD-2-Clause-Patent + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent **/ =20 #include @@ -244,3 +245,28 @@ FindDuplicateValue ( } return FALSE; } + +/** Convert a hex number to its ASCII code. + + @param [in] x Hex number to convert. + Must be 0 <=3D x < 16. + + @return The ASCII code corresponding to x. +**/ +UINT8 +EFIAPI +AsciiFromHex ( + IN UINT8 x + ) +{ + if (x < 10) { + return (UINT8)(x + '0'); + } + + if (x < 16) { + return (UINT8)(x - 10 + 'A'); + } + + ASSERT (FALSE); + return (UINT8)0; +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64100): https://edk2.groups.io/g/devel/message/64100 Mute This Topic: https://groups.io/mt/76149185/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64105+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245850286925.4414024585012; Wed, 12 Aug 2020 08:24:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id uG5NYY1788612xUQEqTW6mJD; Wed, 12 Aug 2020 08:24:09 -0700 X-Received: from EUR04-DB3-obe.outbound.protection.outlook.com (EUR04-DB3-obe.outbound.protection.outlook.com [40.107.6.75]) by mx.groups.io with SMTP id smtpd.web10.17209.1597245838020599223 for ; Wed, 12 Aug 2020 08:23:58 -0700 X-Received: from AM5PR0402CA0022.eurprd04.prod.outlook.com (2603:10a6:203:90::32) by VI1PR08MB4064.eurprd08.prod.outlook.com (2603:10a6:803:e5::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:54 +0000 X-Received: from AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:90:cafe::30) by AM5PR0402CA0022.outlook.office365.com (2603:10a6:203:90::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:54 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64105+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT046.mail.protection.outlook.com (10.152.16.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:54 +0000 X-Received: ("Tessian outbound 7fc8f57bdedc:v64"); Wed, 12 Aug 2020 15:23:54 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: b82936d6c6370133 X-CR-MTA-TID: 64aa7808 X-Received: from 01952ed791eb.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id F2D98007-9F3D-43BC-A4D6-BE447B56B0FF.1; Wed, 12 Aug 2020 15:23:48 +0000 X-Received: from EUR01-DB5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 01952ed791eb.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:48 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=f3xOreTgnVzcdgOf5F44/6gS/0PM0YiBhxTco/bXRv1TY9mDxyMDUlm2WHjtM+/imecK/dR8C4WKVTkRzrc1UemacKZ3pGQ1p7YTtD38hE/koD1nyq5wJtN5HQSjBxND2ddJMyKy55EY64U27VaBLJxuqU/loXTBg5Cc6poERkECahUUH9zl/QYZL25EGiMhYfOjBer0hk1Glq5mLHKzfA0xLGD5tAJURZGiGix+vcaNnFFDqclILQFm2C7Od28vfOWX5805tSfH5NmGtxZ+516uzNsna5G6/tt/UfMshp/LYViDa+5t8apdXJu7lLODgBGQ3iiIUdv80v96ik0taQ== 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-SenderADCheck; bh=pj3bzoZJjBZABuA2N3XH/8tYKHrFVb3AfhYIzecXyoA=; b=T+zj9W6xODXgvR0F8HEoHTU9S/9qzsd1Cr6iJZPrpyCevUUUNzv7oHk3gmfT3P8nCAosCitTo0XW3D2M8p9RkX4ISSn5gejEUu4qKxcNVeSuIQjz7OYLlndataK3BtG7dv/F6anFStzw58Dd65QKQNiKFVJwnLbwJ/WTkt3sdaOel1Q3W0Si76G8fp/1n9dDhVBCXtPvVCXzpSd9+OkQWkynEgrtPRZmHeuzMo7QpAZ3gbtW1s/6MVN8Wg2sFhM2h9PpPp9komtlUhzJJf7QAq2++KKv3EmYx9Md/nwIB6nrGEcTIHCeFiLkYhHHWxQRU/4SO44Bu/oLJykV6FY/jA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6PR10CA0089.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::30) by AM6PR08MB3510.eurprd08.prod.outlook.com (2603:10a6:20b:48::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.17; Wed, 12 Aug 2020 15:23:47 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::9a) by AM6PR10CA0089.outlook.office365.com (2603:10a6:209:8c::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:47 +0000 X-Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:43 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1779.2; Wed, 12 Aug 2020 15:23:42 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:41 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 27/30] DynamicTablesPkg: SSDT Serial Port Fixup library Date: Wed, 12 Aug 2020 16:22:33 +0100 Message-ID: <20200812152236.31164-28-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2cda7776-c26b-44c1-5e7b-08d83ed3b972 X-MS-TrafficTypeDiagnostic: AM6PR08MB3510:|VI1PR08MB4064: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:2958;OLM:2958; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: GHibF5gJ+uS/KX/zC2omY9egbwI9SpSIipn/7D9cmcZwonq94Qew0ovK1ybEwU1Ca4zL7gblmpzFy972lI+nr0R+dKsQNYNSUibRsA3tx9jJxkizgDtDVTUrtYHRzdklC91Irxlbt8hc/epeXWomM6h3vLLNtlD9yqYlBbXHKiTdFOxzKfXCEbGCNc4/LrEVjVRw3q/2QM19rhoNULjZHXHZKiXb2HeOZJ1q2O0Gw2eYzFS6Vgy40IXAwyUzGthmFi+l3j+fQ31vEos7/ePagwm7JRJdRRLuW9E8OgNlVkte6EvBlk1HF1y5XC0qqIuRJMFz1jchKxadcxVhtyR/GMeSmxxp8E45jcsggHMe4B3d7TWEPp7kzz8cnS6iqu4YW0OdR04JtUYfKBx1JgIINA== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(39860400002)(376002)(346002)(396003)(136003)(46966005)(30864003)(47076004)(8676002)(82740400003)(186003)(1076003)(5660300002)(54906003)(36756003)(6666004)(8936002)(44832011)(82310400002)(4326008)(26005)(2616005)(336012)(70206006)(6916009)(45080400002)(7696005)(81166007)(70586007)(83380400001)(356005)(316002)(2906002)(86362001)(426003)(478600001);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3510 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 19c69b36-b247-47ed-187d-08d83ed3b526 X-Microsoft-Antispam-Message-Info: V7ld2FZuBOLUpYNx9s1XU22nqNppMf0E9oYG2kbsTJ3kffXsR7o2RS8PX5bUjoatoqjcol8COQWKvEI4U5T/8vgGVaRmori/im6MB/DUh3FkilXk2Rmtz4SKLICLv4uKPElZfrBNKv8ou2uGeZ47fROEInM5bnm5ZmmdlWWdhMyxOp5woQf9N7nQeEpr8QHd9WfIHa8biOsS5c0rd5gV/u6RSIc87gSy4lyf+3ck0Tl98Sd0/msYgsUdLk05T4YsJv+Ie9Mj2zVxK0ViwJNczWIWDZIqjLnr10HbrFnCUClY0mriE6paI0jHY22WXxkzce/E1bZSg4o4XX+LC5etdKA6T4ljJ658DgZls1iyQvlCR4ZNq3nb4QUgWrRWXyrAGDUKytvf8M/BmyFCVDD6fw== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:54.2477 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 2cda7776-c26b-44c1-5e7b-08d83ed3b972 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: AM5EUR03FT046.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB4064 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: AQGXRPw6V2P6bnSyZHoNvhJTx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245849; bh=1JmkgLXu/fE27/msNdxOJlQwxlEgmhon5BjIBjO9XyY=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=DFDJ3qERW8NnEXW8NqAaK/0QBiD2pmZeVmu6moIkSp1J+H1DGjjOAIrlGhRbrgdi8op lH+NexDE1Hqn37AeDA0fNT+q+9FB8UbOrtj6BFV/fBPVqzH3mO9QwpUxdGJipGJdYaOai zP0yFVD235KKkDYB6YXHYMnnglEFw7+XT8Y= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois According to Arm Server Base Boot Requirements, Platform Design Document version 1.2 revision D, September 2, 2019, section '4.2.1.8 SPCR'; The SPCR console device must be included in the DSDT. Additionally, it is often desirable to describe the serial ports available on a platform so that they are available for use by a rich OS. To facilitate the description of serial ports on a platform a common SSDT Serial Port Fixup library is introduced. It provides interfaces to build a SSDT serial port definition block table based on the serial port information. The SSDT Serial Port Fixup library is used by the SPCR, DBG2 and SSDT Serial Port generator to describe the serial port information in a definition block. +------------+ +------------+ +------------+ | SPCR Gen | | DBG2 Gen | | SERIAL Gen | +------------+ +------------+ +------------+ +----------------------------------+ | SSDT Serial Port Fixup library | +----------------------------------+ The SSDT Serial Port Fixup library: - Parses the SSDT Serial Port template using the AmlLib library to generate an AML tree. - Updates the _UID, _HID and _CID values. - Fixes up the Serial port base address, length and the interrupt number in the _CRS descriptor. - Fixes up the serial-port name. - Serialises the AML Tree to a buffer containing the definition block data. The definition block data is then installed by the corresponding table generator. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/DynamicTables.dsc.inc = | 1 + DynamicTablesPkg/DynamicTablesPkg.ci.yaml = | 3 + DynamicTablesPkg/DynamicTablesPkg.dec = | 3 + DynamicTablesPkg/DynamicTablesPkg.dsc = | 1 + DynamicTablesPkg/Include/AcpiTableGenerator.h = | 7 +- DynamicTablesPkg/Include/ArmNameSpaceObjects.h = | 9 +- DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h = | 68 +++ DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixup= Lib.c | 524 ++++++++++++++++++++ DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixup= Lib.inf | 30 ++ DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortTempl= ate.asl | 60 +++ 10 files changed, 703 insertions(+), 3 deletions(-) diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dyna= micTables.dsc.inc index 928529f797b49f2f0dd52508a9aad557f568719a..0063fc3c671f4ae6089dd4df760= 74445364c6011 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -14,6 +14,7 @@ [BuildOptions] =20 [LibraryClasses.common] AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFix= upLib/SsdtSerialPortFixupLib.inf TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelpe= rLib.inf =20 [Components.common] diff --git a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/DynamicTablesPkg/D= ynamicTablesPkg.ci.yaml index 5ee20357326f4b79444d63418f56aae0b00508de..c0d09e79fdf7f6003b5bbda45ab= c82a0caf4e53f 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml +++ b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml @@ -69,6 +69,8 @@ "IgnoreFiles": [], # use gitignore syntax to ignore erro= rs # in matching files "ExtendWords": [ + "ARMHB", # ARMHB000 + "ARMLTD", "EISAID", "CCIDX", "CCSIDR", @@ -81,6 +83,7 @@ "MPIDR", "pytool", "Roadmap", + "ssdtserialporttemplate", "SMMUV", "standardised", "TABLEEX", diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/Dynam= icTablesPkg.dec index 57e6815fa159c5ce8d5cb0c930375e7322bff211..f36a6e8bb7c17f82acff3c766b1= 5202b064a64b5 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -20,6 +20,9 @@ [LibraryClasses] ## @libraryclass Defines a set of APIs for Dynamic AML generation. AmlLib|Include/Library/AmlLib/AmlLib.h =20 + ## @libraryclass Defines a set of methods for fixing up a SSDT Serial = Port. + SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h + ## @libraryclass Defines a set of helper methods. TableHelperLib|Include/Library/TableHelperLib.h =20 diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/Dynam= icTablesPkg.dsc index add6b192ad4187e2769b374ef68f93a65a1af8b6..0232bda459c87016e1e62f52a5c= 98347e551b14c 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -37,6 +37,7 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64] =20 [Components.common] DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFix= upLib.inf DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf =20 [BuildOptions] diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesP= kg/Include/AcpiTableGenerator.h index b55feb4e7507f0e4e1e0a64c3c4b8068f17dad47..ef5018c312c1abbc205a06b037f= fd6063cf02f0a 100644 --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -55,6 +55,10 @@ The Dynamic Tables Framework implements the following AC= PI table generators: the Configuration Manager and builds the PPTT table. - SRAT : The SRAT generator collates the system resource affinity infor= mation from the Configuration Manager and builds the SRAT table. + - SSDT Serial-Port: + The SSDT Serial generator collates the Serial port information + from the Configuration Manager and patches the SSDT Serial Port + template to build the SSDT Serial port table. */ =20 /** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID. @@ -78,6 +82,7 @@ typedef enum StdAcpiTableId { EStdAcpiTableIdIort, ///< IORT Generator EStdAcpiTableIdPptt, ///< PPTT Generator EStdAcpiTableIdSrat, ///< SRAT Generator + EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Gene= rator EStdAcpiTableIdMax } ESTD_ACPI_TABLE_ID; =20 diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTables= Pkg/Include/ArmNameSpaceObjects.h index 57a282d5cb6883d0dabb74ceac7c8905ed3ef43a..b2534a6505d6fb695f0751bbb09= d365bd93d092e 100644 --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2017 - 2020, ARM Limited. All rights reserved. + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -56,6 +56,7 @@ typedef enum ArmObjectID { EArmObjDeviceHandleAcpi, ///< 32 - Device Handle Acpi EArmObjDeviceHandlePci, ///< 33 - Device Handle Pci EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity + EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info EArmObjMax } EARM_OBJECT_ID; =20 @@ -270,7 +271,8 @@ typedef struct CmArmGicItsInfo { Serial Port information for the Platform. =20 ID: EArmObjSerialConsolePortInfo or - EArmObjSerialDebugPortInfo + EArmObjSerialDebugPortInfo or + EArmObjSerialPortInfo */ typedef struct CmArmSerialPortInfo { /// The physical base address for the serial port @@ -287,6 +289,9 @@ typedef struct CmArmSerialPortInfo { =20 /// Serial Port subtype UINT16 PortSubtype; + + /// The Base address length + UINT64 BaseAddressLength; } CM_ARM_SERIAL_PORT_INFO; =20 /** A structure that describes the diff --git a/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h b/Dy= namicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h new file mode 100644 index 0000000000000000000000000000000000000000..4605f3f34b1d9a2a3af975f8010= 77d6f523e0530 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h @@ -0,0 +1,68 @@ +/** @file + Ssdt Serial Port Fixup Library + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef SSDT_SERIAL_PORT_LIB_H_ +#define SSDT_SERIAL_PORT_LIB_H_ + +/** Build a SSDT table describing the input serial port. + + The table created by this function must be freed by FreeSsdtSerialTable. + + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] SerialPortInfo Serial port to describe in the SSDT table. + @param [in] Name The Name to give to the Device. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + @param [in] Uid UID for the Serial Port. + @param [out] Table If success, pointer to the created SSDT ta= ble. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +BuildSsdtSerialPortTable ( + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo, + IN CONST CHAR8 * Name, + IN CONST UINT64 Uid, + OUT EFI_ACPI_DESCRIPTION_HEADER ** Table + ); + +/** Free an SSDT table previously created by + the BuildSsdtSerialTable function. + + @param [in] Table Pointer to a SSDT table allocated by + the BuildSsdtSerialTable function. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +EFIAPI +FreeSsdtSerialPortTable ( + IN EFI_ACPI_DESCRIPTION_HEADER * Table + ); + +/** Validate the Serial Port Information. + + @param [in] SerialPortInfoTable Table of CM_ARM_SERIAL_PORT_INFO. + @param [in] SerialPortCount Count of SerialPort in the table. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +ValidateSerialPortInfo ( + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfoTable, + IN UINT32 SerialPortCount + ); + +#endif // SSDT_SERIAL_PORT_LIB_H_ diff --git a/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSer= ialPortFixupLib.c b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/= SsdtSerialPortFixupLib.c new file mode 100644 index 0000000000000000000000000000000000000000..944bfd6eaaabc9dbc7223c9888f= b5f11eeb1bda9 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPort= FixupLib.c @@ -0,0 +1,524 @@ +/** @file + SSDT Serial Port Fixup Library. + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - Arm Server Base Boot Requirements (SBBR), s4.2.1.8 "SPCR". + - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** C array containing the compiled AML template. + This symbol is defined in the auto generated C file + containing the AML bytecode array. +*/ +extern CHAR8 ssdtserialporttemplate_aml_code[]; + +/** UART address range length. +*/ +#define MIN_UART_ADDRESS_LENGTH 0x1000U + +/** Validate the Serial Port Information. + + @param [in] SerialPortInfoTable Table of CM_ARM_SERIAL_PORT_INFO. + @param [in] SerialPortCount Count of SerialPort in the table. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +ValidateSerialPortInfo ( + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfoTable, + IN UINT32 SerialPortCount + ) +{ + UINT32 Index; + CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + + if ((SerialPortInfoTable =3D=3D NULL) || + (SerialPortCount =3D=3D 0)) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + for (Index =3D 0; Index < SerialPortCount; Index++) { + SerialPortInfo =3D &SerialPortInfoTable[Index]; + ASSERT (SerialPortInfo !=3D NULL); + + if ((SerialPortInfo =3D=3D NULL ) || + (SerialPortInfo->BaseAddress =3D=3D 0)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: UART port base address is invalid. BaseAddress =3D 0x%llx\= n", + SerialPortInfo->BaseAddress + )); + return EFI_INVALID_PARAMETER; + } + + if ((SerialPortInfo->PortSubtype !=3D + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) && + (SerialPortInfo->PortSubtype !=3D + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) && + (SerialPortInfo->PortSubtype !=3D + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) && + (SerialPortInfo->PortSubtype !=3D + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC) && + (SerialPortInfo->PortSubtype !=3D + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: UART port subtype is invalid." + " UART Base =3D 0x%llx, PortSubtype =3D 0x%x\n", + SerialPortInfo->BaseAddress, + SerialPortInfo->PortSubtype + )); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "UART Configuration:\n")); + DEBUG (( + DEBUG_INFO, + " UART Base =3D 0x%llx\n", SerialPortInfo->BaseAddress + )); + DEBUG (( + DEBUG_INFO, + " Length =3D 0x%llx\n", + SerialPortInfo->BaseAddressLength + )); + DEBUG ((DEBUG_INFO, " Clock =3D %lu\n", SerialPortInfo->Clock)); + DEBUG ((DEBUG_INFO, " BaudRate =3D %llu\n", SerialPortInfo->BaudRat= e)); + DEBUG ((DEBUG_INFO, " Interrupt =3D %lu\n", SerialPortInfo->Interrup= t)); + } // for + + return EFI_SUCCESS; +} + +/** Fixup the Serial Port Ids (_UID, _HID, _CID). + + @param [in] RootNodeHandle Pointer to the root of an AML tree. + @param [in] Uid UID for the Serial Port. + @param [in] SerialPortInfo Pointer to a Serial Port Information + structure. + Get the Serial Port Information from there. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +FixupIds ( + IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle, + IN CONST UINT64 Uid, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE NameOpIdNode; + CONST CHAR8 * HidString; + CONST CHAR8 * CidString; + + // Get the _CID and _HID value to write. + switch (SerialPortInfo->PortSubtype) { + case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550: + { + HidString =3D "PNP0501"; + CidString =3D "PNP0500"; + break; + } + case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART: + { + HidString =3D "ARMH0011"; + CidString =3D "ARMHB000"; + break; + } + case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART: + case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X: + { + HidString =3D "ARMH0011"; + CidString =3D ""; + break; + } + default: + { + return EFI_INVALID_PARAMETER; + } + } // switch + + // Get the _UID NameOp object defined by the "Name ()" statement, + // and update its value. + Status =3D AmlFindNode ( + RootNodeHandle, + "\\_SB_.COM0._UID", + &NameOpIdNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid); + if (EFI_ERROR (Status)) { + return Status; + } + + // Get the _HID NameOp object defined by the "Name ()" statement, + // and update its value. + Status =3D AmlFindNode ( + RootNodeHandle, + "\\_SB_.COM0._HID", + &NameOpIdNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D AmlNameOpUpdateString (NameOpIdNode, HidString); + if (EFI_ERROR (Status)) { + return Status; + } + + // Get the _CID NameOp object defined by the "Name ()" statement, + // and update its value. + Status =3D AmlFindNode ( + RootNodeHandle, + "\\_SB_.COM0._CID", + &NameOpIdNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // If we have a CID then update a _CID node else delete the node. + if (AsciiStrLen (CidString) !=3D 0) { + Status =3D AmlNameOpUpdateString (NameOpIdNode, CidString); + } else { + // First detach the node from the tree. + Status =3D AmlDetachNode (NameOpIdNode); + if (EFI_ERROR (Status)) { + return Status; + } + + // Delete the detached node. + Status =3D AmlDeleteTree (NameOpIdNode); + } + + return Status; +} + +/** Fixup the Serial Port _CRS values (BaseAddress, ...). + + @param [in] RootNodeHandle Pointer to the root of an AML tree. + @param [in] SerialPortInfo Pointer to a Serial Port Information + structure. + Get the Serial Port Information from there. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +FixupCrs ( + IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE NameOpCrsNode; + AML_DATA_NODE_HANDLE QWordRdNode; + AML_DATA_NODE_HANDLE InterruptRdNode; + + // Get the "_CRS" object defined by the "Name ()" statement. + Status =3D AmlFindNode ( + RootNodeHandle, + "\\_SB_.COM0._CRS", + &NameOpCrsNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Get the first Rd node in the "_CRS" object. + Status =3D AmlNameOpCrsGetFirstRdNode (NameOpCrsNode, &QWordRdNode); + if (EFI_ERROR (Status)) { + return Status; + } + + if (QWordRdNode =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // Update the Serial Port base address and length. + Status =3D AmlUpdateRdQWord ( + QWordRdNode, + SerialPortInfo->BaseAddress, + ((SerialPortInfo->BaseAddressLength < MIN_UART_ADDRESS_LENGTH= ) ? + MIN_UART_ADDRESS_LENGTH: SerialPortInfo->BaseAddressLengt= h) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Get the Interrupt node. + // It is the second Resource Data element in the NameOpCrsNode's + // variable list of arguments. + Status =3D AmlNameOpCrsGetNextRdNode (QWordRdNode, &InterruptRdNode); + if (EFI_ERROR (Status)) { + return Status; + } + + if (InterruptRdNode =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // Update the interrupt number. + return AmlUpdateRdInterrupt (InterruptRdNode, SerialPortInfo->Interrupt); +} + +/** Fixup the Serial Port device name. + + @param [in] RootNodeHandle Pointer to the root of an AML tree. + @param [in] SerialPortInfo Pointer to a Serial Port Information + structure. + Get the Serial Port Information from there. + @param [in] Name The Name to give to the Device. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +FixupName ( + IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo, + IN CONST CHAR8 * Name + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE DeviceNode; + + // Get the COM0 variable defined by the "Device ()" statement. + Status =3D AmlFindNode (RootNodeHandle, "\\_SB_.COM0", &DeviceNode); + if (EFI_ERROR (Status)) { + return Status; + } + + // Update the Device's name. + return AmlDeviceOpUpdateName (DeviceNode, (CHAR8*)Name); +} + +/** Fixup the Serial Port Information in the AML tree. + + For each template value: + - find the node to update; + - update the value. + + @param [in] RootNodeHandle Pointer to the root of the AML tree. + @param [in] SerialPortInfo Pointer to a Serial Port Information + structure. + Get the Serial Port Information from there. + @param [in] Name The Name to give to the Device. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + @param [in] Uid UID for the Serial Port. + @param [out] Table If success, contains the serialized + SSDT table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +EFIAPI +FixupSerialPortInfo ( + IN OUT AML_ROOT_NODE_HANDLE RootNodeHandle, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo, + IN CONST CHAR8 * Name, + IN CONST UINT64 Uid, + OUT EFI_ACPI_DESCRIPTION_HEADER ** Table + ) +{ + EFI_STATUS Status; + + ASSERT (RootNodeHandle !=3D NULL); + ASSERT (SerialPortInfo !=3D NULL); + ASSERT (Name !=3D NULL); + ASSERT (Table !=3D NULL); + + // Fixup the _UID, _HID and _CID values. + Status =3D FixupIds (RootNodeHandle, Uid, SerialPortInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // Fixup the _CRS values. + Status =3D FixupCrs (RootNodeHandle, SerialPortInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // Fixup the serial-port name. + // This MUST be done at the end, otherwise AML paths won't be valid anym= ore. + return FixupName (RootNodeHandle, SerialPortInfo, Name); +} + +/** Free an SSDT table previously created by + the BuildSsdtSerialTable function. + + @param [in] Table Pointer to a SSDT table allocated by + the BuildSsdtSerialTable function. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +EFIAPI +FreeSsdtSerialPortTable ( + IN EFI_ACPI_DESCRIPTION_HEADER * Table + ) +{ + ASSERT (Table !=3D NULL); + FreePool (Table); + return EFI_SUCCESS; +} + +/** Build a SSDT table describing the input serial port. + + The table created by this function must be freed by FreeSsdtSerialTable. + + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] SerialPortInfo Serial port to describe in the SSDT table. + @param [in] Name The Name to give to the Device. + Must be a NULL-terminated ASL NameString + e.g.: "DEV0", "DV15.DEV0", etc. + @param [in] Uid UID for the Serial Port. + @param [out] Table If success, pointer to the created SSDT ta= ble. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +BuildSsdtSerialPortTable ( + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo, + IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo, + IN CONST CHAR8 * Name, + IN CONST UINT64 Uid, + OUT EFI_ACPI_DESCRIPTION_HEADER ** Table + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + AML_ROOT_NODE_HANDLE RootNodeHandle; + + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (SerialPortInfo !=3D NULL); + ASSERT (Name !=3D NULL); + ASSERT (Table !=3D NULL); + + // Validate the Serial Port Info. + Status =3D ValidateSerialPortInfo (SerialPortInfo, 1); + if (EFI_ERROR (Status)) { + return Status; + } + + // Parse the SSDT Serial Port Template. + Status =3D AmlParseDefinitionBlock ( + (EFI_ACPI_DESCRIPTION_HEADER*)ssdtserialporttemplate_aml_code, + &RootNodeHandle + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT-FIXUP:" + " Failed to parse SSDT Serial Port Template. Status =3D %r\n", + Status + )); + return Status; + } + + // Fixup the template values. + Status =3D FixupSerialPortInfo ( + RootNodeHandle, + SerialPortInfo, + Name, + Uid, + Table + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to fixup SSDT Serial Port Tab= le." + " Status =3D %r\n", + Status + )); + goto exit_handler; + } + + // Serialize the tree. + Status =3D AmlSerializeDefinitionBlock ( + RootNodeHandle, + Table + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to Serialize SSDT Table Data." + " Status =3D %r\n", + Status + )); + } + +exit_handler: + // Cleanup + if (RootNodeHandle !=3D NULL) { + Status1 =3D AmlDeleteTree (RootNodeHandle); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to cleanup AML tree." + " Status =3D %r\n", + Status1 + )); + // If Status was success but we failed to delete the AML Tree + // return Status1 else return the original error code, i.e. Status. + if (!EFI_ERROR (Status)) { + return Status1; + } + } + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSer= ialPortFixupLib.inf b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLi= b/SsdtSerialPortFixupLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..af3d404393f5f1385ab2d40f45f= 7222ab66f9b3a --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPort= FixupLib.inf @@ -0,0 +1,30 @@ +## @file +# SSDT Serial Port fixup Library +# +# Copyright (c) 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D DynamicSsdtSerialPortFixupLib + FILE_GUID =3D AC5978CC-5B62-4466-AD04-23644C2C38C2 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D SsdtSerialPortFixupLib + +[Sources] + SsdtSerialPortFixupLib.c + SsdtSerialPortTemplate.asl + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + AmlLib + BaseLib + diff --git a/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSer= ialPortTemplate.asl b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLi= b/SsdtSerialPortTemplate.asl new file mode 100644 index 0000000000000000000000000000000000000000..fcae2160ac3df6c3e9e48115b0b= 7195c3001c782 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPort= Template.asl @@ -0,0 +1,60 @@ +/** @file + SSDT Serial Template + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - Arm Server Base Boot Requirements (SBBR), s4.2.1.8 "SPCR". + + @par Glossary: + - {template} - Data fixed up using AML Fixup APIs. +**/ + +DefinitionBlock ("SsdtSerialPortTemplate.aml", "SSDT", 2, "ARMLTD", "SERIA= L", 1) { + Scope (_SB) { + // UART PL011 + Device (COM0) { // {template} + Name (_UID, 0x0) // {template} + Name (_HID, "HID0000") // {template} + Name (_CID, "CID0000") // {template} + + Method(_STA) { + Return(0xF) + } + + Name (_CRS, ResourceTemplate() { + QWordMemory ( + , // ResourceUsage + , // Decode + , // IsMinFixed + , // IsMaxFixed + , // Cacheable + ReadWrite, // ReadAndWrite + 0x0, // AddressGranularity + 0xA0000000, // AddressMinimum // {template} + 0xAFFFFFFF, // AddressMaximum // {template} + 0, // AddressTranslation + 0x10000000, // RangeLength // {template} + , // ResourceSourceIndex + , // ResourceSource + , // DescriptorName + , // MemoryRangeType + // TranslationType + ) // QWordMemory + Interrupt ( + ResourceConsumer, // ResourceUsage + Level, // EdgeLevel + ActiveHigh, // ActiveLevel + Exclusive, // Shared + , // ResourceSourceIndex + , // ResourceSource + // DescriptorName + ) { + 0xA5 // {template} + } // Interrupt + }) // Name + } // Device + } // Scope (_SB) +} --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64105): https://edk2.groups.io/g/devel/message/64105 Mute This Topic: https://groups.io/mt/76149191/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64106+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245851031286.0595442104533; Wed, 12 Aug 2020 08:24:11 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id LXP7YY1788612xnQfTMpANqc; Wed, 12 Aug 2020 08:24:10 -0700 X-Received: from EUR03-DB5-obe.outbound.protection.outlook.com (EUR03-DB5-obe.outbound.protection.outlook.com [40.107.4.80]) by mx.groups.io with SMTP id smtpd.web10.17211.1597245838881721382 for ; Wed, 12 Aug 2020 08:23:59 -0700 X-Received: from AM6P193CA0132.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::37) by HE1PR0801MB1737.eurprd08.prod.outlook.com (2603:10a6:3:81::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.20; Wed, 12 Aug 2020 15:23:55 +0000 X-Received: from AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:85:cafe::a4) by AM6P193CA0132.outlook.office365.com (2603:10a6:209:85::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:55 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64106+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT023.mail.protection.outlook.com (10.152.16.169) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:55 +0000 X-Received: ("Tessian outbound 195a290eb161:v64"); Wed, 12 Aug 2020 15:23:55 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: e9e355f06b233710 X-CR-MTA-TID: 64aa7808 X-Received: from e7b6d5c4f804.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 74C50AC5-5661-4006-B24D-F6B3A98A0541.1; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id e7b6d5c4f804.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hTsxlIjkctp5Aqzd8YaosDeRQ0+sqRAjA/HZmvph+qcFWfaf5picjf7d75x/lRxbT0AttQJefRVWxnJsEZpZ8RvEXCWp5D+SeQ2M1vOpuvLLBkZrDP+P3BAFIDnKdZ5IIB18Hf6TiFv4sOvAZDF7JuAt9FABZFXgmuOW0EPwNo+B8ugyUunE/ycnswoutloB7rcOdzUTBI4NrQNoMjbXPhEL9jPl4bpmbbwfl8AYlpcE4vUCjfqGTSUKTV8IrAevWetbMX49CRbPl1nRWDuohd/hDNNZXugeebAQ4DA4Udtn2//cunLdWGxgqQBh6ueMiO5DP6hBdPYgiCEPaKOkMQ== 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-SenderADCheck; bh=dfRP1oPy3gtySCnk0Y6psdHwxqX/mMcxz/GqfkLpKcw=; b=bTuKI4gelrgbqJodSFR2frauE1CCYI/vO4mD+9HXDT43CiMN359kgrx9JGQvA7KTQcCBbrQYCP9NX2lewFO6Fy+ZCIULk6aqB/Ec//Vcvqt/7SmHxCXLrRKwQNNqMwkNlUd/fflIYqVt13Y4iFV2f+Mt0Nv5XreaY2JSfccwOHkuv0DLkTRz53v7VsH3F288NSP95Ir26Ra43wW9BmvhA8gv1PXQqtzf/Kcva0VbDQN4jX5688epHz2wi9ADOvS0piO413QFQLWxusO8Z2rNDtlsUE/+UgzhCnXS7bpjpUlkSiGKbaH1sB/xTTv7mQ7AHQhIoUUTc9XrWpbiSx3iPA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6PR10CA0094.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::35) by DB7PR08MB3561.eurprd08.prod.outlook.com (2603:10a6:10:42::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.20; Wed, 12 Aug 2020 15:23:47 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::d2) by AM6PR10CA0094.outlook.office365.com (2603:10a6:209:8c::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:47 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:43 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:43 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 28/30] DynamicTablesPkg: SSDT Serial Port generator Date: Wed, 12 Aug 2020 16:22:34 +0100 Message-ID: <20200812152236.31164-29-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bf8b0558-7cb6-4832-24b7-08d83ed3ba50 X-MS-TrafficTypeDiagnostic: DB7PR08MB3561:|HE1PR0801MB1737: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4941;OLM:4941; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: a/900oeVxs87yGZpZBwXUdGEZxA+2q5tpWWaRXyJ+QsfJVksa7Qz5e0UDdf7TQYT6Q3buXFkgfZIfocR4ItZigvB/CwX5bVGo4dzL6/CZfJ9UppnWO5TZB3+29WNnDyuCPETV8VhOJpspGpGwSz0Jnx7gEx9/y8+A+j/eZ45qvW4DAeRF5EH4QhybbQZdw0bYelR/PaVShCcd8eNPAT7Sg64irbaNl3RiB2DZ+Dd2to98cLxv8cMrYT4Cv2flBswrrS4KGzthTJi2RZNU11feNmn1ywqaBEi0YUJEa0+XerA+6HNBZiRdH/UreLRw8tUFMPv+tH0o+fS6hmnRdseMQkI5BF5/Qqw4VKtLap+l4g7wZiqrL4qzIX2yH4bqaVXsamopmzjtyYfZu0oAecrPg== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(396003)(136003)(39860400002)(376002)(346002)(46966005)(86362001)(82310400002)(81166007)(83380400001)(426003)(6666004)(356005)(478600001)(316002)(5660300002)(54906003)(2906002)(2616005)(8676002)(8936002)(36756003)(6916009)(336012)(44832011)(4326008)(1076003)(30864003)(7696005)(47076004)(70586007)(26005)(70206006)(82740400003)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR08MB3561 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 28b099cf-ec6d-4dba-7f7c-08d83ed3b596 X-Microsoft-Antispam-Message-Info: 0if1engwv5blVB0WpqJRd3uoSZw4GMsYQeUBVE2ExcWdxhaTkKmnoiz7CuBDSb/fJIuvZCbppL8IFSrUzD+FfxgNILqxBEhoEygtR0dNFw5idzeJES95OnC/pr//PT+2iZuQFsPNiSoF2X35MD4eAndsI/MqkLFLJa3f460fn2WIeXR4WMKC3hfAoVJtxuDD0F+uUYZ6uL6YcXTrPA2zWF59zgDLdwwZHEYWqDzep2U9VYLb4oRLPnZEarxPm3ONgdNh7aPoDoqHolPcssgHDFCQagyq2tWvg8cN3ikmjX8VMo7qEatD/D1Z4NVwfnavbg3rQy+9kP/XijV2fF04cMpqH9oumTzsvTeqeTuEQRc9CwP1mQ8uEzTJpfbetKH8SkReL4NdoEymH7Bv6qYFzQ== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:55.7011 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bf8b0558-7cb6-4832-24b7-08d83ed3ba50 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: AM5EUR03FT023.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0801MB1737 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: 0ApWER0JN0GfDOpCIe4dELvtx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245850; bh=j834mpeN4aKFs/4LqrxrZ1Eal/Io7ETSkZlhUig+A7A=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=jE3MKIMwpvjbZJIUHNbPXMJ3faAc9Es0ehm9I/UXC0cWYRvgTTcxfNlsrAx0Vx0sGPH YqC9CY6siypnkIG3PdOXixn44KDRYlFBARQjX9Q//+0rYqN5U3ACIdhIBAUCCBX8SUMam 3YgxQDNTC51/yA7TFTrHs/rxI4aPTTs7N0Y= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois Most platforms have several serial ports. These serial ports are described to an operating system using definition block tables. The SSDT Serial Port Table Generator uses the Configuration Manager protocol to obtain information for the Serial Ports on the platform. The serial ports are described using the CM_ARM_SERIAL_PORT_INFO structure. The EArmObjSerialPortInfo ID is used to represent a standard serial port. The SSDT Serial port fixup library provides interfaces to generate a SSDT Serial port table based on the serial port information. The SSDT Serial Port Table Generator uses the SSDT serial port fixup library to build serial port definition blocks and installs the SSDT tables. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/DynamicTables.dsc.inc = | 6 + DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortG= enerator.c | 367 ++++++++++++++++++++ DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortL= ibArm.inf | 33 ++ 3 files changed, 406 insertions(+) diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dyna= micTables.dsc.inc index 0063fc3c671f4ae6089dd4df76074445364c6011..7fb14d8d1463f7d4502fd3a7708= bc94bc336357d 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -32,6 +32,9 @@ [Components.common] DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf =20 + # AML Fixup + DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPor= tLibArm.inf + # # Dynamic Table Factory Dxe # @@ -47,6 +50,9 @@ [Components.common] NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.i= nf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm= .inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm= .inf + + # AML Fixup + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/Ssdt= SerialPortLibArm.inf } =20 # diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/Ssd= tSerialPortGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPo= rtLibArm/SsdtSerialPortGenerator.c new file mode 100644 index 0000000000000000000000000000000000000000..2197e50dc714707f7ed7cc37759= d3dba5a45f0e0 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerial= PortGenerator.c @@ -0,0 +1,367 @@ +/** @file + SSDT Serial Port Table Generator. + + Copyright (c) 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** ARM standard SSDT Serial Port Table Generator + + Constructs SSDT tables describing serial ports (other than the serial po= rts + used by the SPCR or DBG2 tables). + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArmObjSerialPortInfo +*/ + +/** This macro expands to a function that retrieves the Serial-port + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjSerialPortInfo, + CM_ARM_SERIAL_PORT_INFO + ); + +/** Starting value for the UID to represent the serial ports. + Note: The UID 0 and 1 are reserved for use by DBG2 port and SPCR + respectively. So, the UIDs for serial ports for general use + start at 2. +*/ +#define SERIAL_PORT_START_UID 2 + +/** Maximum serial ports supported by this generator. + This generator supports a maximum of 14 (16 - 2) serial ports. + The -2 here reflects the reservation for serial ports for the DBG2 + and SPCR ports regardless of whether the DBG2 or SPCR port is enabled. + Note: This is not a hard limitation and can be extended if needed. + Corresponding changes would be needed to support the Name and + UID fields describing the serial port. + +*/ +#define MAX_SERIAL_PORTS_SUPPORTED 14 + +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSsdtSerialPortTableEx ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableIn= fo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProto= col, + IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; + UINTN Index; + + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + + if ((Table =3D=3D NULL) || + (*Table =3D=3D NULL) || + (TableCount =3D=3D 0)) { + DEBUG ((DEBUG_ERROR, "ERROR: SSDT-SERIAL-PORT: Invalid Table Pointer\n= ")); + return EFI_INVALID_PARAMETER; + } + + TableList =3D *Table; + + for (Index =3D 0; Index < TableCount; Index++) { + if ((TableList[Index] !=3D NULL) && + (TableList[Index]->Signature =3D=3D + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { + Status =3D FreeSsdtSerialPortTable (TableList[Index]); + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Could not free SSDT table at index %d." + " Status =3D %r\n", + Index, + Status + )); + return Status; + } + } //for + + // Free the table list. + FreePool (*Table); + + return EFI_SUCCESS; +} + +/** Construct SSDT tables describing serial-ports. + + 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 FreeXXXXTableResourcesEx function. + + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s= ). + @param [out] TableCount Number of generated ACPI table(s). + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtSerialPortTableEx ( + IN CONST ACPI_TABLE_GENERATOR * This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER *** Table, + OUT UINTN * CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + UINT32 SerialPortCount; + UINTN Index; + CHAR8 NewName[] =3D "COMx"; + UINT64 Uid; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; + + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (Table !=3D NULL); + ASSERT (TableCount !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); + + *Table =3D NULL; + + Status =3D GetEArmObjSerialPortInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SerialPortInfo, + &SerialPortCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to get serial port information." + " Status =3D %r\n", + Status + )); + return Status; + } + + if (SerialPortCount > MAX_SERIAL_PORTS_SUPPORTED) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Too many serial ports: %d." + " Maximum serial ports supported =3D %d.\n", + SerialPortCount, + MAX_SERIAL_PORTS_SUPPORTED + )); + return EFI_INVALID_PARAMETER; + } + + // Validate the SerialPort info. + Status =3D ValidateSerialPortInfo (SerialPortInfo, SerialPortCount); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Invalid serial port information. Status = =3D %r\n", + Status + )); + return Status; + } + + // Allocate a table to store pointers to the SSDT tables. + TableList =3D (EFI_ACPI_DESCRIPTION_HEADER**) + AllocateZeroPool ( + (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * SerialPortCount) + ); + if (TableList =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to allocate memory for Table List." + " Status =3D %r\n", + Status + )); + return Status; + } + + // Setup the table list early so that that appropriate cleanup + // can be done in case of failure. + *Table =3D TableList; + + for (Index =3D 0; Index < SerialPortCount; Index++) { + Uid =3D SERIAL_PORT_START_UID + Index; + NewName[3] =3D AsciiFromHex ((UINT8)(Uid)); + + // Build a SSDT table describing the serial port. + Status =3D BuildSsdtSerialPortTable ( + AcpiTableInfo, + &SerialPortInfo[Index], + NewName, + Uid, + &TableList[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to build associated SSDT table." + " Status =3D %r\n", + Status + )); + goto error_handler; + } + + // Increment the table count here so that appropriate cleanup + // can be done in case of failure. + *TableCount +=3D 1; + } // for + +error_handler: + // Note: Table list and Serial port count has been setup. The + // error handler does nothing here as the framework will invoke + // FreeSsdtSerialPortTableEx() even on failure. + return Status; +} + +/** This macro defines the SSDT Serial Port Table Generator revision. +*/ +#define SSDT_SERIAL_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SSDT Serial Port Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR SsdtSerialPortGenerator =3D { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtSerialPort), + // Generator Description + L"ACPI.STD.SSDT.SERIAL.PORT.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_SERIAL_GENERATOR_REVISION, + // Build table function. Use the extended version instead. + NULL, + // Free table function. Use the extended version instead. + NULL, + // Extended Build table function. + BuildSsdtSerialPortTableEx, + // Extended free function. + FreeSsdtSerialPortTableEx +}; + +/** 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 +AcpiSsdtSerialPortLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * SystemTable + ) +{ + EFI_STATUS Status; + Status =3D RegisterAcpiTableGenerator (&SsdtSerialPortGenerator); + DEBUG (( + DEBUG_INFO, + "SSDT-SERIAL-PORT: 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 +AcpiSsdtSerialPortLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * SystemTable + ) +{ + EFI_STATUS Status; + Status =3D DeregisterAcpiTableGenerator (&SsdtSerialPortGenerator); + DEBUG (( + DEBUG_INFO, + "SSDT-SERIAL-PORT: Deregister Generator. Status =3D %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/Ssd= tSerialPortLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPor= tLibArm/SsdtSerialPortLibArm.inf new file mode 100644 index 0000000000000000000000000000000000000000..fb7663e280ad9dc81ac5d3f8fce= de883319a569f --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerial= PortLibArm.inf @@ -0,0 +1,33 @@ +## @file +# Ssdt Serial Port Table Generator +# +# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D SsdtSerialPortLibArm + FILE_GUID =3D D1F92325-2DFB-435C-9B4C-A6B864F19230 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D NULL|DXE_DRIVER + CONSTRUCTOR =3D AcpiSsdtSerialPortLibConstructor + DESTRUCTOR =3D AcpiSsdtSerialPortLibDestructor + +[Sources] + SsdtSerialPortGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + AmlLib + BaseLib + TableHelperLib + SsdtSerialPortFixupLib --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64106): https://edk2.groups.io/g/devel/message/64106 Mute This Topic: https://groups.io/mt/76149192/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64107+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245851939391.6408709246142; Wed, 12 Aug 2020 08:24:11 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id mze4YY1788612xN7KT5MxuuO; Wed, 12 Aug 2020 08:24:11 -0700 X-Received: from EUR03-AM5-obe.outbound.protection.outlook.com (EUR03-AM5-obe.outbound.protection.outlook.com [40.107.3.83]) by mx.groups.io with SMTP id smtpd.web10.17212.1597245839147752244 for ; Wed, 12 Aug 2020 08:23:59 -0700 X-Received: from MR2P264CA0071.FRAP264.PROD.OUTLOOK.COM (2603:10a6:500:31::35) by VE1PR08MB5152.eurprd08.prod.outlook.com (2603:10a6:803:109::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Wed, 12 Aug 2020 15:23:56 +0000 X-Received: from VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com (2603:10a6:500:31:cafe::76) by MR2P264CA0071.outlook.office365.com (2603:10a6:500:31::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:56 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64107+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT028.mail.protection.outlook.com (10.152.18.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:55 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:55 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 3b8d97003a880db5 X-CR-MTA-TID: 64aa7808 X-Received: from e2fd11da9c51.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id A2EB9D91-52EB-4705-8EF3-A3437DD82898.1; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from EUR02-AM5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id e2fd11da9c51.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gbRs5NlmLls5n29yQX9FhDZuT9oR3gmf49AjsPNEOP6GBSwD5BH5vk9EVy3W5gf37sEUOLgxtLWg8H5Vf1GK15J1cy+zqQ6c1bz3AEvyGfnBgroML4zeQb7oUpeMKsFfv+XXEuvIt+1q/cHhMbEt1qm3Tis5vX7AdMk8I0hPlfPo2LolAxxE6vWgwM2jqNAduwW+RAldpBzscpJsEBXap5cxgkWc5qwhcxN+cTV4z8wRlVB0FWFXdQbeTxldjFQzicWb+EtZB1D9mBsmDlNkRn/zHti2RnKuqLidA0zOQAZ4SfRYw4xcOm+iwgv5yEmJTpaSgzfRlr04l808bXVxmw== 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-SenderADCheck; bh=kvtA68BYBTidU9sBLa5+UtCVqXCK/+wphUm70TR6o/g=; b=hBjdl2Ki2vqKYLgmohuKosoTCe4fTTX07CcarHe6JiVWtfS6ZI2VZQRq7RaP/t4e1oL/2/yGx/U8SVJM84xwGomYTQ2aadVfaDa3sU3hOoMHjkTzWCNbCUfsAPNkC6EtgHLdxjZaL+55hxi61vOginSfP4pnik31TZWK30EQh/pGaIeq1xlwrN8aOb7lHNaOcd/gyP+Ye3Qtka07JZXSLwYyPKqzJ9E1ySSv7h2Ed+5s5tAo1cIypNfFtdajScoXjrN712shQRsmaXUJIXWr52NdwIArjhXufzhqfqS2oP1DjAwBFhnswoidqi/o3Kr8tx+SA+LgjHlyL2Uw9oBQ6w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM6PR10CA0095.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:209:8c::36) by DBBPR08MB4887.eurprd08.prod.outlook.com (2603:10a6:10:d7::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15; Wed, 12 Aug 2020 15:23:49 +0000 X-Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8c:cafe::b2) by AM6PR10CA0095.outlook.office365.com (2603:10a6:209:8c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.15 via Frontend Transport; Wed, 12 Aug 2020 15:23:49 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:48 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:44 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:44 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 29/30] DynamicTablesPkg: Add SSDT Serial port for SPCR Date: Wed, 12 Aug 2020 16:22:35 +0100 Message-ID: <20200812152236.31164-30-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 1f8902ef-ebc4-4fe7-8e0f-08d83ed3ba63 X-MS-TrafficTypeDiagnostic: DBBPR08MB4887:|VE1PR08MB5152: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4941;OLM:4941; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(4636009)(346002)(136003)(376002)(396003)(39860400002)(46966005)(81166007)(47076004)(336012)(426003)(6666004)(186003)(82740400003)(2906002)(70586007)(1076003)(6916009)(26005)(36756003)(70206006)(356005)(5660300002)(7696005)(2616005)(478600001)(30864003)(44832011)(4326008)(86362001)(316002)(83380400001)(8936002)(8676002)(82310400002)(54906003);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4887 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 564b0ae5-b3e6-45ec-b7eb-08d83ed3b647 X-Microsoft-Antispam-Message-Info: JhB7nAc+T8O2LskDPCO9o666iQBtLr4X6+cfod9Bp0PPM8Ngs3BBkaXO1YaLLquwfOwH7yq+U74N0czUdfuadU48mpncTPHUQ2eDF+UWbWyhLwdVepp155v/GBzMaDG2fSI3bbVrzwoeawgiUi+OskVzrrGlTfuuU5StvMONKrajPc1PK6XslSwGkUUeenwNtHsbcCbtfhq0dllycbxpHCuNtJjwrF0ZezdHU6rdQkhQSsohEgdzAMKhLTsdhxTlxEbN4GhVb2mamfS4d03iGQcCMW68rQzmAWXLSBHON9oJTuROZ0QfZU0T2FLlmWdgeyJUKi/7SD5igJI2/AxK5h18HyHZ4SF6WhDXKsnpY/lTi3SnIGf1U+JYvfkbjNfHqkj+rwyi0+yxzrWGTrFn5A== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:55.7554 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1f8902ef-ebc4-4fe7-8e0f-08d83ed3ba63 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: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR08MB5152 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: MS7nFvL5niDIRR64iw446bs5x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245851; bh=kjQVOQpg/lu0lAzFxAa7wLq5616bA11vKIfd2DSo6lI=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=FP8sJg+IqHXpa9zxNZo40NSBqK5/c3UlyNFBFMqAGu4sADxThWdFTk1/fJJP/1QN6ZN G9CF1CLuGwoBzXfy1y+cIU3g0TnvSVBGEfVpBwZwYRKxdiOGDKkWojCjPINGC3Pu9S0wZ 4Yc40wRrehkGNkv+hrNdIIFfO7Ap4dipu3A= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois According to Arm Server Base Boot Requirements, Platform Design Document version 1.2 revision D, September 2, 2019, section '4.2.1.8 SPCR'; the SPCR console device must be included in the DSDT. The SSDT Serial port fixup library provides interfaces to generate a SSDT Serial port table based on the serial port information. Update the SPCR Generator to use the SSDT serial port fixup library to build a serial port definition block corresponding to the SPCR serial port and install the SSDT table. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf | 3 = +- DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c | 219 = ++++++++++++++------ 2 files changed, 162 insertions(+), 60 deletions(-) diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibAr= m.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf index 0ebe1ffbbdf0b53d9bab4fe454dffdceaeb7f48b..e11f878ec83e050592c8b0428c0= 1c2eafba37cd8 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf @@ -1,7 +1,7 @@ ## @file # SPCR Table Generator # -# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -27,6 +27,7 @@ [Packages] =20 [LibraryClasses] BaseLib + SsdtSerialPortFixupLib =20 [Pcd] =20 diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator= .c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c index b80e98ee7e143e39c540557d53a4129bf4ac5eb7..24bb5c014607b0746c4a8bb8bd2= 60510fbdff08b 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c @@ -1,7 +1,8 @@ /** @file SPCR Table Generator =20 - Copyright (c) 2017 - 2020, ARM Limited. All rights reserved. + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent =20 @par Reference(s): @@ -14,12 +15,14 @@ #include #include #include +#include #include =20 // Module specific include files. #include #include #include +#include #include #include =20 @@ -40,6 +43,14 @@ NOTE: This implementation ignores the possibility that t= he Serial settings may =20 #pragma pack(1) =20 +/** A string representing the name of the SPCR port. +*/ +#define NAME_STR_SPCR_PORT "COM1" + +/** An UID representing the SPCR port. +*/ +#define UID_SPCR_PORT 1 + /** This macro defines the no flow control option. */ #define SPCR_FLOW_CONTROL_NONE 0 @@ -92,47 +103,111 @@ GET_OBJECT_LIST ( CM_ARM_SERIAL_PORT_INFO ) =20 -/** Construct the SPCR ACPI table. +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSpcrTableEx ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableIn= fo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProto= col, + IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; + + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); + + if ((Table =3D=3D NULL) || + (*Table =3D=3D NULL) || + (TableCount !=3D 2)) { + DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList =3D *Table; + + if ((TableList[1] =3D=3D NULL) || + (TableList[1]->Signature !=3D + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n")); + return EFI_INVALID_PARAMETER; + } + + // Only need to free the SSDT table at index 1. The SPCR table is static. + Status =3D FreeSsdtSerialPortTable (TableList[1]); + ASSERT_EFI_ERROR (Status); + + // Free the table list. + FreePool (*Table); + + return Status; +} + +/** Construct the SPCR ACPI table and its associated SSDT table. =20 This function invokes the Configuration Manager protocol interface to get the required hardware information for generating the ACPI table. =20 If this function allocates any resources then they must be freed - in the FreeXXXXTableResources function. + in the FreeXXXXTableResourcesEx function. =20 - @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. + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s= ). + @param [out] TableCount Number of generated ACPI table(s). =20 - @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_UNSUPPORTED An unsupported baudrate was specified by t= he - Configuration Manager. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for t= he - requested object. + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. **/ STATIC EFI_STATUS EFIAPI -BuildSpcrTable ( - 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 +BuildSpcrTableEx ( + IN CONST ACPI_TABLE_GENERATOR * This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER *** Table, + OUT UINTN * CONST TableCount ) { - EFI_STATUS Status; - CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + EFI_STATUS Status; + CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + UINT32 SerialPortCount; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; =20 ASSERT (This !=3D NULL); ASSERT (AcpiTableInfo !=3D NULL); ASSERT (CfgMgrProtocol !=3D NULL); ASSERT (Table !=3D NULL); + ASSERT (TableCount !=3D NULL); ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); =20 @@ -155,7 +230,7 @@ BuildSpcrTable ( CfgMgrProtocol, CM_NULL_TOKEN, &SerialPortInfo, - NULL + &SerialPortCount ); if (EFI_ERROR (Status)) { DEBUG (( @@ -163,44 +238,46 @@ BuildSpcrTable ( "ERROR: SPCR: Failed to get serial port information. Status =3D %r\n= ", Status )); - goto error_handler; + return Status; } =20 - if (SerialPortInfo->BaseAddress =3D=3D 0) { - Status =3D EFI_INVALID_PARAMETER; + if (SerialPortCount =3D=3D 0) { DEBUG (( DEBUG_ERROR, - "ERROR: SPCR: Uart port base address is invalid. BaseAddress =3D 0x%= lx\n", - SerialPortInfo->BaseAddress + "ERROR: SPCR: Serial port information not found. Status =3D %r\n", + EFI_NOT_FOUND )); - goto error_handler; + return EFI_NOT_FOUND; } =20 - if ((SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) { - Status =3D EFI_INVALID_PARAMETER; + // Validate the SerialPort info. Only one SPCR port can be described. + // If platform provides description for multiple SPCR ports, use the + // first SPCR port information. + Status =3D ValidateSerialPortInfo (SerialPortInfo, 1); + if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "ERROR: SPCR: Uart port subtype is invalid. PortSubtype =3D 0x%x\n", - SerialPortInfo->PortSubtype + "ERROR: SPCR: Invalid serial port information. Status =3D %r\n", + Status )); - goto error_handler; + return Status; } =20 - DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n")); - DEBUG ((DEBUG_INFO, " UART Base =3D 0x%lx\n", SerialPortInfo->BaseAddr= ess)); - DEBUG ((DEBUG_INFO, " Clock =3D %d\n", SerialPortInfo->Clock)); - DEBUG ((DEBUG_INFO, " Baudrate =3D %ld\n", SerialPortInfo->BaudRate)); - DEBUG ((DEBUG_INFO, " Interrupt =3D %d\n", SerialPortInfo->Interrupt)); + // Allocate a table to store pointers to the SPCR and SSDT tables. + TableList =3D (EFI_ACPI_DESCRIPTION_HEADER**) + AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * 2); + if (TableList =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to allocate memory for Table List," \ + " Status =3D %r\n", + Status + )); + return Status; + } =20 + // Build SPCR table. Status =3D AddAcpiHeader ( CfgMgrProtocol, This, @@ -267,9 +344,35 @@ BuildSpcrTable ( goto error_handler; } // switch =20 - *Table =3D (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr; + TableList[0] =3D (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr; + + // Build a SSDT table describing the serial port. + Status =3D BuildSsdtSerialPortTable ( + AcpiTableInfo, + SerialPortInfo, + NAME_STR_SPCR_PORT, + UID_SPCR_PORT, + &TableList[1] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to build associated SSDT table. Status =3D %r\n= ", + Status + )); + goto error_handler; + } + + *TableCount =3D 2; + *Table =3D TableList; + + return Status; =20 error_handler: + if (TableList !=3D NULL) { + FreePool (TableList); + } + return Status; } =20 @@ -287,7 +390,7 @@ ACPI_TABLE_GENERATOR SpcrGenerator =3D { // Generator Description L"ACPI.STD.SPCR.GENERATOR", // ACPI Table Signature - EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, + EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, // ACPI Table Revision supported by this Generator EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, // Minimum supported ACPI Table Revision @@ -296,16 +399,14 @@ ACPI_TABLE_GENERATOR SpcrGenerator =3D { TABLE_GENERATOR_CREATOR_ID_ARM, // Creator Revision SPCR_GENERATOR_REVISION, - // Build Table function - BuildSpcrTable, - // No additional resources are allocated by the generator. - // Hence the Free Resource function is not required. + // Build table function. Use the extended version instead. NULL, - // Extended build function not needed + // Free table function. Use the extended version instead. NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL + // Extended Build table function. + BuildSpcrTableEx, + // Extended free function. + FreeSpcrTableEx }; =20 /** Register the Generator with the ACPI Table Factory. --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64107): https://edk2.groups.io/g/devel/message/64107 Mute This Topic: https://groups.io/mt/76149193/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 14:23:51 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+64108+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1597245852279750.429770752687; Wed, 12 Aug 2020 08:24:12 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id whogYY1788612xITmpguAE7N; Wed, 12 Aug 2020 08:24:11 -0700 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com (EUR05-DB8-obe.outbound.protection.outlook.com [40.107.20.81]) by mx.groups.io with SMTP id smtpd.web12.16989.1597245841767433673 for ; Wed, 12 Aug 2020 08:24:02 -0700 X-Received: from MR2P264CA0066.FRAP264.PROD.OUTLOOK.COM (2603:10a6:500:31::30) by AM5PR0802MB2402.eurprd08.prod.outlook.com (2603:10a6:203:a1::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.16; Wed, 12 Aug 2020 15:23:58 +0000 X-Received: from VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com (2603:10a6:500:31:cafe::cc) by MR2P264CA0066.outlook.office365.com (2603:10a6:500:31::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:58 +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=bestguesspass action=none header.from=arm.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+64108+1787277+3901457@groups.io; helo=web01.groups.io; 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; X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT028.mail.protection.outlook.com (10.152.18.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:58 +0000 X-Received: ("Tessian outbound a0bffebca527:v64"); Wed, 12 Aug 2020 15:23:58 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: c30cb861c7dad406 X-CR-MTA-TID: 64aa7808 X-Received: from 7c045cdf71a9.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id D8F30D48-2299-42BC-AED4-3AC58EF68326.1; Wed, 12 Aug 2020 15:23:52 +0000 X-Received: from EUR01-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 7c045cdf71a9.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 12 Aug 2020 15:23:52 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FmN5Smw7Rqi1tNxxg6Mkv9StQhc1p+2TjkD+qBBEoYVkP+/yoj5Lx3kYmagEELCy7r8GTU6byyroeQlq3ltKWHokAh+nYcJ+4cbD9qG3UT8xhkb2IPleFMo12x3BJIAXO+1rZQLsSMMn4zKdwGE8GS3uj2IYYdHjKr5Uweu0qx5lH60o64R5cGtwTbxd/i/IWqqlg7HJnG30EDGmnu8S3GrOFV4QYRLTUWfq1yksgOVJ57Wes4MgG4hlPNIorPyxbH9Uz72nWDtFdPKQm3zAYdbcTSbYKOfDVc+0Od8IWNd7QCu3YcAu/mTcgE6H/X45C6s+fOeo2/gOp2AmGGjpuA== 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-SenderADCheck; bh=zrLrA+5nj1xTg0KI5PUWP5XLnbxc79w9bFPr9aTR8Wg=; b=IyZ9RmMBhVG0/cZ8XZXeqC+3yRFj9ga//SYy95yk5qBod2y2XHiS3qRgJ1X4YarQYem8SDi+/QKHAhixK8zVD8zjxvh8qsRqcoYegG4Tr+NztlI01DPH36iaH1NW7lGsayo3YHjXyxNVtRBR/l8Z/zcJwE9QlqiFgsKYK+BZaaK+biGv/ka38qe/98u2ZYr/hfYTKcEcdp1odLIucjlBzeDcX+jx8dwiTuNyw/jker9NN55MDIRRmGvN1xN6Cn5Qc2RyeICNGPev2XCBPgchfRb5RS1mSi7mfoIBFkLcLq5YlPdqZca5Da8EyeCxmvoNpQiVR6nBasTBmuxAXwdYRg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=bestguesspass action=none header.from=arm.com; dkim=none (message not signed); arc=none X-Received: from AM5PR0402CA0001.eurprd04.prod.outlook.com (2603:10a6:203:90::11) by VI1PR08MB3264.eurprd08.prod.outlook.com (2603:10a6:803:4b::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.20; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from AM5EUR03FT057.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:90:cafe::da) by AM5PR0402CA0001.outlook.office365.com (2603:10a6:203:90::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:50 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; X-Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT057.mail.protection.outlook.com (10.152.17.44) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3283.16 via Frontend Transport; Wed, 12 Aug 2020 15:23:50 +0000 X-Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Wed, 12 Aug 2020 15:23:45 +0000 X-Received: from E107187.Arm.com (10.57.41.222) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2044.4 via Frontend Transport; Wed, 12 Aug 2020 15:23:44 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , Subject: [edk2-devel] [PATCH v1 30/30] DynamicTablesPkg: Add SSDT Serial port for DBG2 Date: Wed, 12 Aug 2020 16:22:36 +0100 Message-ID: <20200812152236.31164-31-sami.mujawar@arm.com> In-Reply-To: <20200812152236.31164-1-sami.mujawar@arm.com> References: <20200812152236.31164-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 67e6cb57-06dd-4146-f3d2-08d83ed3bbe2 X-MS-TrafficTypeDiagnostic: VI1PR08MB3264:|AM5PR0802MB2402: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:4941;OLM:4941; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: ceDkrnWA1tZ1ondlv9+ZUBWGBxg3Zf6ZDdKvYs+KtKQAsxRK9aSkO+vQgpLGEF03vyZ2zqDJYPuJYeJdp3OxxoQMGPopShd8fFM/nPM9LvTMmYTPvIQnAAP3Ju6mF+C95DgGwRVXItWV2hFzojHeowOs69th9dDiHM02pVX0nr8+Kc7wilioBsw+pziMFxanAxcd+kFoFC66IF6ffl1PgztRYAgZ+Na07oJvqRy7IO2/4e5fS+u4p8UQuKlAz12hH/9AaixEKooS/n+uUFvENC4Py30IjhEwv9LSR84jk2mZIHtBNGRLOKxI+CvrS0V3pEK75ueGQH1FZhcrX5FapLNCbLPMMzSRKnKArO6FfteHJHlH59gHf3XRCUntLzWOp0AkP4YeFpcccQUECgJsTA== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFTY:;SFS:(4636009)(136003)(346002)(376002)(39860400002)(396003)(46966005)(83380400001)(6916009)(86362001)(81166007)(2906002)(478600001)(426003)(47076004)(186003)(70586007)(70206006)(4326008)(316002)(36756003)(26005)(336012)(5660300002)(82740400003)(7696005)(1076003)(8936002)(54906003)(44832011)(6666004)(8676002)(19627235002)(82310400002)(2616005)(30864003)(356005);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB3264 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 13c7c9ed-887a-41e7-3726-08d83ed3b716 X-Microsoft-Antispam-Message-Info: xYkkRmFy19j9BKq4zaQFAavMUbG1IwNIgmKRWl0rYA/xnX+HZQo4UMT/JNHGrYlpAjYFCdWmSFHGsXcJRZzW0LXM3KKWe44eYng7r2aH/AJbp2/70KcnpvVIBSRJ0rXvKpgSWK12BLa2rhh9ao9QInseNpUCUM1OeQwbpXiATkxwzn1PlDt7ctTSVf37suGPiw307EqcCqP3gMJuBT8y3n6BXwSYL+KCL1TCgc2oFGqpzwPZMHbmIi4b4X+ru7OugoVZFScqISeGIUQXuG/t1MKOvxBPgNosggmk/lOdRQC9nENMqR0DIk5LqrEkmxOwNoFq8dyjSvgQ0i17E+OgV4CoX9CS/9ELIi7Sn+/u+8639yIs6Kt9L2pZ2sWQcZxk/vSLxFAzULa5RfxtoIMPYA== X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2020 15:23:58.2670 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 67e6cb57-06dd-4146-f3d2-08d83ed3bbe2 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: VE1EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0802MB2402 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com X-Gm-Message-State: mBARuiTsVProX3DSJtxXM6HEx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1597245851; bh=DWTmrajlpRsjkbCjbrc+9XIg6KeOZ2uBo4Gb4XOfG5w=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=Px6QUokBRdLEp715g60a6qRGEVmEYOTCCVMV+V4RPfxh4jHD9h03t/JH5Zb+4lV93+g VzLuXiAlKRbbaV0d+pnDk0vBth8NViYINyOslk7IDDACuZlS5veKxPD9m2CNTqEMfU5Xt 6xZh4SEtchCG2OWRxdy8whUcp0JVQE0HeyE= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Pierre Gondois The SSDT Serial port fixup library provides interfaces to generate a SSDT Serial port table based on the serial port information. Update the DBG2 Generator to use the SSDT serial port fixup library to build a serial port definition block for the DBG2 serial port and install the SSDT table. Signed-off-by: Pierre Gondois Signed-off-by: Sami Mujawar Reviewed-by: Alexei Fedorov --- DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf | 3 = +- DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c | 228 = ++++++++++++++------ 2 files changed, 163 insertions(+), 68 deletions(-) diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibAr= m.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf index 0f8d3cd687700d01fce6ced5d31a7a2b890bc551..f7b7c1c025a68989166faf34915= e1754bfb44ad0 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf @@ -1,7 +1,7 @@ ## @file # DBG2 Table Generator # -# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -29,6 +29,7 @@ [Packages] [LibraryClasses] BaseLib PL011UartLib + SsdtSerialPortFixupLib =20 [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator= .c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c index 172d99f61cf36e7e65d62249960fd7527d8dae00..d902bbc8463921624f1a6333e8d= 6bd84c6cb38f2 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c @@ -1,7 +1,8 @@ /** @file DBG2 Table Generator =20 - Copyright (c) 2017 - 2020, ARM Limited. All rights reserved. + Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent =20 @par Reference(s): @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +22,7 @@ #include #include #include +#include #include #include =20 @@ -44,17 +47,21 @@ Requirements: */ #define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1 =20 -/** The index for the debug port 1 in the Debug port information list. +/** The index for the debug port 0 in the Debug port information list. */ -#define DBG_PORT_INDEX_PORT1 0 +#define INDEX_DBG_PORT0 0 =20 -/** A string representing the name of the debug port 1. +/** A string representing the name of the debug port 0. */ -#define NAME_STR_PORT1 "COM1" +#define NAME_STR_DBG_PORT0 "COM0" + +/** An UID representing the debug port 0. +*/ +#define UID_DBG_PORT0 0 =20 /** The length of the namespace string. */ -#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_PORT1) +#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_DBG_PO= RT0) =20 /** The PL011 UART address range length. */ @@ -159,7 +166,7 @@ DBG2_TABLE AcpiDbg2 =3D { 0, // {Template}: Serial Port Subtype 0, // {Template}: Serial Port Base Address PL011_UART_LENGTH, - NAME_STR_PORT1 + NAME_STR_DBG_PORT0 ) } }; @@ -217,58 +224,115 @@ SetupDebugUart ( &StopBits ); =20 - DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n")); - DEBUG ((DEBUG_INFO, "UART Base =3D 0x%lx\n", SerialPortInfo->BaseAddres= s)); - DEBUG ((DEBUG_INFO, "Clock =3D %d\n", SerialPortInfo->Clock)); - DEBUG ((DEBUG_INFO, "Baudrate =3D %ld\n", BaudRate)); - DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status =3D %r\n", Status)); - ASSERT_EFI_ERROR (Status); return Status; } =20 -/** Construct the DBG2 ACPI table +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeDbg2TableEx ( + IN CONST ACPI_TABLE_GENERATOR * CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableIn= fo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProto= col, + IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; + + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); + + if ((Table =3D=3D NULL) || + (*Table =3D=3D NULL) || + (TableCount !=3D 2)) { + DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList =3D *Table; + + if ((TableList[1] =3D=3D NULL) || + (TableList[1]->Signature !=3D + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n")); + return EFI_INVALID_PARAMETER; + } + + // Only need to free the SSDT table at index 1. The DBG2 table is static. + Status =3D FreeSsdtSerialPortTable (TableList[1]); + ASSERT_EFI_ERROR (Status); + + // Free the table list. + FreePool (*Table); + + return Status; +} =20 - The BuildDbg2Table function is called by the Dynamic Table Manager - to construct the DBG2 ACPI table. +/** Construct the DBG2 ACPI table and its associated SSDT table. =20 This function invokes the Configuration Manager protocol interface to get the required hardware information for generating the ACPI table. =20 If this function allocates any resources then they must be freed - in the FreeXXXXTableResources function. + in the FreeXXXXTableResourcesEx function. =20 - @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. + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s= ). + @param [out] TableCount Number of generated ACPI table(s). =20 - @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. + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. **/ STATIC EFI_STATUS EFIAPI -BuildDbg2Table ( - 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 +BuildDbg2TableEx ( + IN CONST ACPI_TABLE_GENERATOR * This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER *** Table, + OUT UINTN * CONST TableCount ) { - EFI_STATUS Status; - CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + EFI_STATUS Status; + CM_ARM_SERIAL_PORT_INFO * SerialPortInfo; + UINT32 SerialPortCount; + EFI_ACPI_DESCRIPTION_HEADER ** TableList; =20 ASSERT (This !=3D NULL); ASSERT (AcpiTableInfo !=3D NULL); ASSERT (CfgMgrProtocol !=3D NULL); ASSERT (Table !=3D NULL); + ASSERT (TableCount !=3D NULL); ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignatur= e); =20 @@ -291,7 +355,7 @@ BuildDbg2Table ( CfgMgrProtocol, CM_NULL_TOKEN, &SerialPortInfo, - NULL + &SerialPortCount ); if (EFI_ERROR (Status)) { DEBUG (( @@ -299,34 +363,41 @@ BuildDbg2Table ( "ERROR: DBG2: Failed to get serial port information. Status =3D %r\n= ", Status )); - goto error_handler; + return Status; } =20 - if (SerialPortInfo->BaseAddress =3D=3D 0) { - Status =3D EFI_INVALID_PARAMETER; + if (SerialPortCount =3D=3D 0) { DEBUG (( DEBUG_ERROR, - "ERROR: DBG2: Uart port base address is invalid. BaseAddress =3D 0x%= lx\n", - SerialPortInfo->BaseAddress + "ERROR: DBG2: Serial port information not found. Status =3D %r\n", + EFI_NOT_FOUND )); - goto error_handler; + return EFI_NOT_FOUND; } =20 - if ((SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) && - (SerialPortInfo->PortSubtype !=3D - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) { - Status =3D EFI_INVALID_PARAMETER; + // Only use the first DBG2 port information. + Status =3D ValidateSerialPortInfo (SerialPortInfo, 1); + if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "ERROR: DBG2: Uart port subtype is invalid. PortSubtype =3D 0x%x\n", - SerialPortInfo->PortSubtype + "ERROR: DBG2: Invalid serial port information. Status =3D %r\n", + Status )); - goto error_handler; + return Status; + } + + // Allocate a table to store pointers to the DBG2 and SSDT tables. + TableList =3D (EFI_ACPI_DESCRIPTION_HEADER**) + AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * 2); + if (TableList =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to allocate memory for Table List," \ + " Status =3D %r\n", + Status + )); + return Status; } =20 Status =3D AddAcpiHeader ( @@ -346,11 +417,11 @@ BuildDbg2Table ( } =20 // Update the base address - AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Addres= s =3D + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.Address =3D SerialPortInfo->BaseAddress; =20 // Update the serial port subtype - AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].Dbg2Device.PortSubtype =3D + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype =3D SerialPortInfo->PortSubtype; =20 if ((SerialPortInfo->PortSubtype =3D=3D @@ -371,9 +442,35 @@ BuildDbg2Table ( } } =20 - *Table =3D (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2; + TableList[0] =3D (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2; + + // Build a SSDT table describing the serial port. + Status =3D BuildSsdtSerialPortTable ( + AcpiTableInfo, + SerialPortInfo, + NAME_STR_DBG_PORT0, + UID_DBG_PORT0, + &TableList[1] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to build associated SSDT table. Status =3D %r\n= ", + Status + )); + goto error_handler; + } + + *TableCount =3D 2; + *Table =3D TableList; + + return Status; =20 error_handler: + if (TableList !=3D NULL) { + FreePool (TableList); + } + return Status; } =20 @@ -391,7 +488,7 @@ ACPI_TABLE_GENERATOR Dbg2Generator =3D { // Generator Description L"ACPI.STD.DBG2.GENERATOR", // ACPI Table Signature - EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, + EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE, // ACPI Table Revision supported by this Generator EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, // Minimum supported ACPI Table Revision @@ -400,16 +497,14 @@ ACPI_TABLE_GENERATOR Dbg2Generator =3D { TABLE_GENERATOR_CREATOR_ID_ARM, // Creator Revision DBG2_GENERATOR_REVISION, - // Build Table function - BuildDbg2Table, - // No additional resources are allocated by the generator. - // Hence the Free Resource function is not required. + // Build table function. Use the extended version instead. NULL, - // Extended build function not needed + // Free table function. Use the extended version instead. NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL + // Extended Build table function. + BuildDbg2TableEx, + // Extended free function. + FreeDbg2TableEx }; =20 /** Register the Generator with the ACPI Table Factory. @@ -433,7 +528,6 @@ AcpiDbg2LibConstructor ( Status =3D RegisterAcpiTableGenerator (&Dbg2Generator); DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status =3D %r\n", Status)= ); ASSERT_EFI_ERROR (Status); - return Status; } =20 --=20 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=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 (#64108): https://edk2.groups.io/g/devel/message/64108 Mute This Topic: https://groups.io/mt/76149194/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-