https://git.reactos.org/?p=reactos.git;a=commitdiff;h=60f018aea6226390a09c6…
commit 60f018aea6226390a09c6cfb327cb340b1c18169
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Wed Jan 2 23:29:12 2019 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
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;
}
}