]> git.proxmox.com Git - mirror_edk2.git/commitdiff
DynamicTablesPkg: Helper function to compute package length
authorPierre Gondois <Pierre.Gondois@arm.com>
Fri, 8 Oct 2021 14:46:24 +0000 (15:46 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 8 Oct 2021 15:39:42 +0000 (15:39 +0000)
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 <sami.mujawar@arm.com>
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c
DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h

index eadafca97ea5c0e84718923c3297ada828593666..d829b1869846863c83dceca884b3ff663906996e 100644 (file)
@@ -2,7 +2,7 @@
   AML grammar definitions.\r
 \r
   Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
-  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+  Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>\r
 \r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 **/\r
@@ -803,3 +803,88 @@ AmlComputePkgLengthWidth (
   // Length < 2^6\r
   return 1;\r
 }\r
+\r
+/** Given a length, compute the value of a PkgLen.\r
+\r
+  In AML, some object have a PkgLen, telling the size of the AML object.\r
+  It can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is\r
+  itself counted in the PkgLen value.\r
+  This means that if an AML object sees its size increment/decrement,\r
+  the number of bytes used to encode the PkgLen value can itself\r
+  increment/decrement.\r
+\r
+  For instance, the AML encoding of a DeviceOp is:\r
+    DefDevice := DeviceOp PkgLength NameString TermList\r
+  If:\r
+   - sizeof (NameString) = 4 (the name is "DEV0" for instance);\r
+   - sizeof (TermList) = (2^6-6)\r
+  then the PkgLen is encoded on 1 byte. Indeed, its value is:\r
+    sizeof (PkgLen) + sizeof (NameString) + sizeof (TermList) =\r
+    sizeof (PkgLen) + 4 + (2^6-6)\r
+  So:\r
+    PkgLen = sizeof (PkgLen) + (2^6-2)\r
+\r
+  The input arguments Length and PkgLen represent, for the DefDevice:\r
+    DefDevice := DeviceOp PkgLength NameString TermList\r
+                                    |------Length-----|\r
+                          |--------*PgkLength---------|\r
+\r
+  @param  [in]  Length  The length to encode as a PkgLen.\r
+                        Length cannot exceed 2^28 - 4 (4 bytes for the\r
+                        PkgLen encoding).\r
+                        The size of the PkgLen encoding bytes should not be\r
+                        counted in this length value.\r
+  @param  [out] PkgLen  If success, contains the value of the PkgLen,\r
+                        ready to encode in the PkgLen format.\r
+                        This value takes into account the size of PkgLen\r
+                        encoding.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlComputePkgLength (\r
+  IN  UINT32    Length,\r
+  OUT UINT32  * PkgLen\r
+  )\r
+{\r
+  UINT32  PkgLenWidth;\r
+  UINT32  ReComputedPkgLenWidth;\r
+\r
+  if (PkgLen == NULL) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  // Compute the PkgLenWidth.\r
+  PkgLenWidth = AmlComputePkgLengthWidth (Length);\r
+  if (PkgLenWidth == 0) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  // Add it to the Length.\r
+  Length += PkgLenWidth;\r
+\r
+  // Check that adding the PkgLenWidth didn't trigger a domino effect,\r
+  // increasing the encoding width of the PkgLen again.\r
+  // The PkgLen is encoded in at most 4 bytes. It is possible to increase\r
+  // the PkgLen width if its encoding is less than 3 bytes.\r
+  ReComputedPkgLenWidth = AmlComputePkgLengthWidth (Length);\r
+  if (ReComputedPkgLenWidth != PkgLenWidth) {\r
+    if ((ReComputedPkgLenWidth != 0)   &&\r
+        (ReComputedPkgLenWidth < 4)) {\r
+      // No need to recompute the PkgLen since a new threshold cannot\r
+      // be reached by incrementing the value by one.\r
+      Length += 1;\r
+    } else {\r
+      ASSERT (0);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  *PkgLen = Length;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
index 35c0680b615987f81ca786cb420deccd19fce071..0641500fcd5f5df76774b90bad648e1b5dd66e78 100644 (file)
@@ -2,7 +2,7 @@
   AML grammar definitions.\r
 \r
   Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
-  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+  Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>\r
 \r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 **/\r
@@ -326,5 +326,50 @@ AmlComputePkgLengthWidth (
   IN  UINT32  Length\r
   );\r
 \r
+/** Given a length, compute the value of a PkgLen.\r
+\r
+  In AML, some object have a PkgLen, telling the size of the AML object.\r
+  It can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is\r
+  itself counted in the PkgLen value.\r
+  This means that if an AML object sees its size increment/decrement,\r
+  the number of bytes used to encode the PkgLen value can itself\r
+  increment/decrement.\r
+\r
+  For instance, the AML encoding of a DeviceOp is:\r
+    DefDevice := DeviceOp PkgLength NameString TermList\r
+  If:\r
+   - sizeof (NameString) = 4 (the name is "DEV0" for instance);\r
+   - sizeof (TermList) = (2^6-6)\r
+  then the PkgLen is encoded on 1 byte. Indeed, its value is:\r
+    sizeof (PkgLen) + sizeof (NameString) + sizeof (TermList) =\r
+    sizeof (PkgLen) + 4 + (2^6-6)\r
+  So:\r
+    PkgLen = sizeof (PkgLen) + (2^6-2)\r
+\r
+  The input arguments Length and PkgLen represent, for the DefDevice:\r
+    DefDevice := DeviceOp PkgLength NameString TermList\r
+                                    |------Length-----|\r
+                          |--------*PgkLength---------|\r
+\r
+  @param  [in]  Length  The length to encode as a PkgLen.\r
+                        Length cannot exceed 2^28 - 4 (4 bytes for the\r
+                        PkgLen encoding).\r
+                        The size of the PkgLen encoding bytes should not be\r
+                        counted in this length value.\r
+  @param  [out] PkgLen  If success, contains the value of the PkgLen,\r
+                        ready to encode in the PkgLen format.\r
+                        This value takes into account the size of PkgLen\r
+                        encoding.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlComputePkgLength (\r
+  IN  UINT32    Length,\r
+  OUT UINT32  * PkgLen\r
+  );\r
+\r
 #endif // AML_H_\r
 \r