From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web08.10313.1633704416815814264 for ; Fri, 08 Oct 2021 07:46:57 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: pierre.gondois@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7E4401063; Fri, 8 Oct 2021 07:46:56 -0700 (PDT) Received: from e120189.arm.com (unknown [10.57.73.60]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7432A3F66F; Fri, 8 Oct 2021 07:46:55 -0700 (PDT) From: "PierreGondois" To: devel@edk2.groups.io, Sami Mujawar , Alexei.Fedorov@arm.com Subject: [PATCH v3 13/21] DynamicTablesPkg: Helper function to compute package length Date: Fri, 8 Oct 2021 15:46:24 +0100 Message-Id: <20211008144632.31894-14-Pierre.Gondois@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211008144632.31894-1-Pierre.Gondois@arm.com> References: <20211008144632.31894-1-Pierre.Gondois@arm.com> From: Pierre Gondois Some AML object have a PkgLen which indicates the size of the AML object. The package length can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is itself counted in the PkgLen value. So, if an AML object's size increments/decrements, the number of bytes used to encode the PkgLen value can itself increment/decrement. Therefore, a helper function AmlComputePkgLength() is introduced to simply computation of the PkgLen. Reviewed-by: Sami Mujawar Signed-off-by: Pierre Gondois --- .../Library/Common/AmlLib/AmlEncoding/Aml.c | 87 ++++++++++++++++++- .../Library/Common/AmlLib/AmlEncoding/Aml.h | 47 +++++++++- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c index eadafca97ea5..d829b1869846 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c @@ -2,7 +2,7 @@ AML grammar definitions. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
- Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -803,3 +803,88 @@ AmlComputePkgLengthWidth ( // Length < 2^6 return 1; } + +/** Given a length, compute the value of a PkgLen. + + In AML, some object have a PkgLen, telling the size of the AML object. + It can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is + itself counted in the PkgLen value. + This means that if an AML object sees its size increment/decrement, + the number of bytes used to encode the PkgLen value can itself + increment/decrement. + + For instance, the AML encoding of a DeviceOp is: + DefDevice := DeviceOp PkgLength NameString TermList + If: + - sizeof (NameString) = 4 (the name is "DEV0" for instance); + - sizeof (TermList) = (2^6-6) + then the PkgLen is encoded on 1 byte. Indeed, its value is: + sizeof (PkgLen) + sizeof (NameString) + sizeof (TermList) = + sizeof (PkgLen) + 4 + (2^6-6) + So: + PkgLen = sizeof (PkgLen) + (2^6-2) + + The input arguments Length and PkgLen represent, for the DefDevice: + DefDevice := DeviceOp PkgLength NameString TermList + |------Length-----| + |--------*PgkLength---------| + + @param [in] Length The length to encode as a PkgLen. + Length cannot exceed 2^28 - 4 (4 bytes for the + PkgLen encoding). + The size of the PkgLen encoding bytes should not be + counted in this length value. + @param [out] PkgLen If success, contains the value of the PkgLen, + ready to encode in the PkgLen format. + This value takes into account the size of PkgLen + encoding. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlComputePkgLength ( + IN UINT32 Length, + OUT UINT32 * PkgLen + ) +{ + UINT32 PkgLenWidth; + UINT32 ReComputedPkgLenWidth; + + if (PkgLen == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Compute the PkgLenWidth. + PkgLenWidth = AmlComputePkgLengthWidth (Length); + if (PkgLenWidth == 0) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Add it to the Length. + Length += PkgLenWidth; + + // Check that adding the PkgLenWidth didn't trigger a domino effect, + // increasing the encoding width of the PkgLen again. + // The PkgLen is encoded in at most 4 bytes. It is possible to increase + // the PkgLen width if its encoding is less than 3 bytes. + ReComputedPkgLenWidth = AmlComputePkgLengthWidth (Length); + if (ReComputedPkgLenWidth != PkgLenWidth) { + if ((ReComputedPkgLenWidth != 0) && + (ReComputedPkgLenWidth < 4)) { + // No need to recompute the PkgLen since a new threshold cannot + // be reached by incrementing the value by one. + Length += 1; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + *PkgLen = Length; + + return EFI_SUCCESS; +} diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h index 35c0680b6159..0641500fcd5f 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h +++ b/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h @@ -2,7 +2,7 @@ AML grammar definitions. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
- Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -326,5 +326,50 @@ AmlComputePkgLengthWidth ( IN UINT32 Length ); +/** Given a length, compute the value of a PkgLen. + + In AML, some object have a PkgLen, telling the size of the AML object. + It can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is + itself counted in the PkgLen value. + This means that if an AML object sees its size increment/decrement, + the number of bytes used to encode the PkgLen value can itself + increment/decrement. + + For instance, the AML encoding of a DeviceOp is: + DefDevice := DeviceOp PkgLength NameString TermList + If: + - sizeof (NameString) = 4 (the name is "DEV0" for instance); + - sizeof (TermList) = (2^6-6) + then the PkgLen is encoded on 1 byte. Indeed, its value is: + sizeof (PkgLen) + sizeof (NameString) + sizeof (TermList) = + sizeof (PkgLen) + 4 + (2^6-6) + So: + PkgLen = sizeof (PkgLen) + (2^6-2) + + The input arguments Length and PkgLen represent, for the DefDevice: + DefDevice := DeviceOp PkgLength NameString TermList + |------Length-----| + |--------*PgkLength---------| + + @param [in] Length The length to encode as a PkgLen. + Length cannot exceed 2^28 - 4 (4 bytes for the + PkgLen encoding). + The size of the PkgLen encoding bytes should not be + counted in this length value. + @param [out] PkgLen If success, contains the value of the PkgLen, + ready to encode in the PkgLen format. + This value takes into account the size of PkgLen + encoding. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +AmlComputePkgLength ( + IN UINT32 Length, + OUT UINT32 * PkgLen + ); + #endif // AML_H_ -- 2.17.1