+\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