https://git.reactos.org/?p=reactos.git;a=commitdiff;h=60f018aea6226390a09c6cfb327cb340b1c18169

commit 60f018aea6226390a09c6cfb327cb340b1c18169
Author:     Eric Kohl <[email protected]>
AuthorDate: Wed Jan 2 23:29:12 2019 +0100
Commit:     Eric Kohl <[email protected]>
CommitDate: Wed Jan 2 23:29:12 2019 +0100

    [ACPI] Add code to retrieve packet type data from ACPI methods. This will 
enable the cmbatt driver to retrieve _BIF (battery information) or _BST 
(battery status) data. Also fix the buffer size calculation for integer and 
string data.
---
 drivers/bus/acpi/eval.c | 127 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 106 insertions(+), 21 deletions(-)

diff --git a/drivers/bus/acpi/eval.c b/drivers/bus/acpi/eval.c
index 7d10b486db..2d338272e7 100644
--- a/drivers/bus/acpi/eval.c
+++ b/drivers/bus/acpi/eval.c
@@ -3,6 +3,83 @@
 #define NDEBUG
 #include <debug.h>
 
+static
+NTSTATUS
+GetPackageSize(ACPI_OBJECT *Package,
+               PULONG Count,
+               PULONG Size)
+{
+    ULONG Length, RawLength, TotalLength;
+    UINT32 i;
+
+    TotalLength = 0;
+    for (i = 0; i < Package->Package.Count; i++)
+    {
+        switch (Package->Package.Elements[i].Type)
+        {
+            case ACPI_TYPE_INTEGER:
+                Length = sizeof(ACPI_METHOD_ARGUMENT);
+                DPRINT("Integer %lu -> %lu: %lu (0x%lx)\n", sizeof(ULONG), 
Length, Package->Package.Elements[i].Integer.Value);
+                TotalLength += Length;
+                break;
+
+            case ACPI_TYPE_STRING:
+                RawLength = Package->Package.Elements[i].String.Length + 1;
+                Length = sizeof(ACPI_METHOD_ARGUMENT);
+                if (RawLength > sizeof(ULONG))
+                    Length += RawLength - sizeof(ULONG);
+                DPRINT("String %lu -> %lu: '%s'\n", RawLength, Length, 
Package->Package.Elements[i].String.Pointer);
+                TotalLength += Length;
+                break;
+
+            default:
+                DPRINT1("Unsupported element type %lu\n", 
Package->Package.Elements[i].Type);
+                return STATUS_UNSUCCESSFUL;
+        }
+    }
+
+    *Count = Package->Package.Count;
+    *Size = TotalLength;
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+ConvertPackageArguments(ACPI_METHOD_ARGUMENT *Argument,
+                        ACPI_OBJECT *Package)
+{
+    ACPI_METHOD_ARGUMENT *Ptr;
+    UINT32 i;
+
+    Ptr = Argument;
+    for (i = 0; i < Package->Package.Count; i++)
+    {
+        switch (Package->Package.Elements[i].Type)
+        {
+            case ACPI_TYPE_INTEGER:
+                DPRINT("Integer %lu\n", sizeof(ACPI_METHOD_ARGUMENT));
+                ACPI_METHOD_SET_ARGUMENT_INTEGER(Ptr, 
Package->Package.Elements[i].Integer.Value);
+                break;
+
+            case ACPI_TYPE_STRING:
+                DPRINT("String %lu\n", 
Package->Package.Elements[i].String.Length);
+                ACPI_METHOD_SET_ARGUMENT_STRING(Ptr, 
Package->Package.Elements[i].String.Pointer);
+                break;
+
+            default:
+                DPRINT1("Unsupported element type %lu\n", 
Package->Package.Elements[i].Type);
+                return STATUS_UNSUCCESSFUL;
+        }
+
+        Ptr = ACPI_METHOD_NEXT_ARGUMENT(Ptr);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 NTAPI
 Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
@@ -83,7 +160,8 @@ Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
   if (ACPI_SUCCESS(Status))
   {
       ACPI_OBJECT *Obj = RetBuff.Pointer;
-      ULONG ExtraParamLength;
+      ULONG ExtraParamLength = 0;
+      ULONG Count = 1;
 
       /* If we didn't get anything back then we're done */
       if (!RetBuff.Pointer || RetBuff.Length == 0)
@@ -92,39 +170,43 @@ Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
       switch (Obj->Type)
       {
           case ACPI_TYPE_INTEGER:
-             ExtraParamLength = sizeof(ULONG);
+             ExtraParamLength = sizeof(ACPI_METHOD_ARGUMENT);
              break;
 
           case ACPI_TYPE_STRING:
-             ExtraParamLength = Obj->String.Length;
+             ExtraParamLength = sizeof(ACPI_METHOD_ARGUMENT);
+             if (Obj->String.Length + 1 > sizeof(ULONG))
+                 ExtraParamLength += Obj->String.Length + 1 - sizeof(ULONG);
              break;
 
           case ACPI_TYPE_BUFFER:
-             ExtraParamLength = Obj->Buffer.Length;
+             ExtraParamLength = sizeof(ACPI_METHOD_ARGUMENT);
+             if (Obj->Buffer.Length > sizeof(ULONG))
+                 ExtraParamLength += Obj->Buffer.Length + 1 - sizeof(ULONG);
              break;
 
           case ACPI_TYPE_PACKAGE:
              DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
-             return STATUS_UNSUCCESSFUL;
+             Status = GetPackageSize(Obj, &Count, &ExtraParamLength);
+             if (!NT_SUCCESS(Status))
+                 return Status;
+             break;
 
           default:
              ASSERT(FALSE);
              return STATUS_UNSUCCESSFUL;
       }
 
-      /* Enough space for a ULONG is always included */
-      if (ExtraParamLength >= sizeof(ULONG))
-          ExtraParamLength -= sizeof(ULONG);
-      else
-          ExtraParamLength = 0;
-
-      OutputBuf = ExAllocatePoolWithTag(NonPagedPool, 
sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
-                                               ExtraParamLength, 'BpcA');
-      if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES;
+      DPRINT("ExtraParamLength %lu\n", ExtraParamLength);
+      OutputBuf = ExAllocatePoolWithTag(NonPagedPool,
+                                        sizeof(ACPI_EVAL_OUTPUT_BUFFER) - 
sizeof(ACPI_METHOD_ARGUMENT) + ExtraParamLength,
+                                        'BpcA');
+      if (!OutputBuf)
+          return STATUS_INSUFFICIENT_RESOURCES;
 
       OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
-      OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT);
-      OutputBuf->Count = 1;
+      OutputBuf->Length = ExtraParamLength;
+      OutputBuf->Count = Count;
 
       switch (Obj->Type)
       {
@@ -142,19 +224,22 @@ Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
 
           case ACPI_TYPE_PACKAGE:
              DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
-             return STATUS_UNSUCCESSFUL;
+             Status = ConvertPackageArguments(OutputBuf->Argument, Obj);
+             if (!NT_SUCCESS(Status))
+                 return Status;
+             break;
 
           default:
              ASSERT(FALSE);
              return STATUS_UNSUCCESSFUL;
       }
 
-      if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 
sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
+      if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 
sizeof(ACPI_EVAL_OUTPUT_BUFFER) - sizeof(ACPI_METHOD_ARGUMENT) +
                                                                   
ExtraParamLength)
       {
-          RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, 
sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
+          RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, 
sizeof(ACPI_EVAL_OUTPUT_BUFFER) - sizeof(ACPI_METHOD_ARGUMENT) +
                                                                     
ExtraParamLength);
-          Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 
ExtraParamLength;
+          Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) - 
sizeof(ACPI_METHOD_ARGUMENT) + ExtraParamLength;
           ExFreePoolWithTag(OutputBuf, 'BpcA');
           return STATUS_SUCCESS;
       }
@@ -166,7 +251,7 @@ Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
   }
   else
   {
-      DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, 
DeviceData->AcpiHandle);
+      DPRINT1("Query method %4s failed on %p\n", EvalInputBuff->MethodName, 
DeviceData->AcpiHandle);
       return STATUS_UNSUCCESSFUL; 
   }
 }

Reply via email to