[ACPI]
[reactos.git] / reactos / drivers / bus / acpi / eval.c
1 #include <ntddk.h>
2
3 #include <acpi.h>
4
5 #include <acpisys.h>
6 #include <acpi_bus.h>
7 #include <acpi_drivers.h>
8 #include <acpiioct.h>
9
10 #include <glue.h>
11 #include <accommon.h>
12 #include <acobject.h>
13 #include <actypes.h>
14
15 #include <wdmguid.h>
16 #define NDEBUG
17 #include <debug.h>
18
19 NTSTATUS
20 NTAPI
21 Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
22 PIRP Irp)
23 {
24 ULONG Signature;
25 NTSTATUS Status;
26 ACPI_OBJECT_LIST *ParamList;
27 PACPI_EVAL_INPUT_BUFFER EvalInputBuff = Irp->AssociatedIrp.SystemBuffer;
28 ACPI_BUFFER RetBuff = {ACPI_ALLOCATE_BUFFER, NULL};
29 PACPI_EVAL_OUTPUT_BUFFER OutputBuf;
30 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
31
32 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
33 return STATUS_INVALID_PARAMETER;
34
35 Signature = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
36
37 switch (Signature)
38 {
39 case ACPI_EVAL_INPUT_BUFFER_SIGNATURE:
40 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER))
41 return STATUS_INVALID_PARAMETER;
42
43 ParamList = NULL;
44 break;
45
46 /* FIXME: Support input parameters */
47
48 default:
49 DPRINT1("Unsupported input buffer signature: %d\n", Signature);
50 return STATUS_NOT_IMPLEMENTED;
51 }
52
53 Status = AcpiEvaluateObject(DeviceData->AcpiHandle,
54 (CHAR*)EvalInputBuff->MethodName,
55 ParamList,
56 &RetBuff);
57 if (ACPI_SUCCESS(Status))
58 {
59 ACPI_OBJECT *Obj = RetBuff.Pointer;
60 ULONG ExtraParamLength;
61
62 switch (Obj->Type)
63 {
64 case ACPI_TYPE_INTEGER:
65 ExtraParamLength = sizeof(ULONG);
66 break;
67
68 case ACPI_TYPE_STRING:
69 ExtraParamLength = Obj->String.Length;
70 break;
71
72 case ACPI_TYPE_BUFFER:
73 ExtraParamLength = Obj->Buffer.Length;
74 break;
75
76 case ACPI_TYPE_PACKAGE:
77 DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
78 return STATUS_UNSUCCESSFUL;
79
80 default:
81 ASSERT(FALSE);
82 return STATUS_UNSUCCESSFUL;
83 }
84
85 /* Enough space for a ULONG is always included */
86 if (ExtraParamLength >= sizeof(ULONG))
87 ExtraParamLength -= sizeof(ULONG);
88 else
89 ExtraParamLength = 0;
90
91 OutputBuf = ExAllocatePool(NonPagedPool, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
92 ExtraParamLength);
93 if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES;
94
95 OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
96 OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT);
97 OutputBuf->Count = 1;
98
99 switch (Obj->Type)
100 {
101 case ACPI_TYPE_INTEGER:
102 ACPI_METHOD_SET_ARGUMENT_INTEGER(OutputBuf->Argument, Obj->Integer.Value);
103 break;
104
105 case ACPI_TYPE_STRING:
106 ACPI_METHOD_SET_ARGUMENT_STRING(OutputBuf->Argument, Obj->String.Pointer);
107 break;
108
109 case ACPI_TYPE_BUFFER:
110 ACPI_METHOD_SET_ARGUMENT_BUFFER(OutputBuf->Argument, Obj->Buffer.Pointer, Obj->Buffer.Length);
111 break;
112
113 case ACPI_TYPE_PACKAGE:
114 DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
115 return STATUS_UNSUCCESSFUL;
116
117 default:
118 ASSERT(FALSE);
119 return STATUS_UNSUCCESSFUL;
120 }
121
122 if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
123 ExtraParamLength)
124 {
125 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
126 ExtraParamLength);
127 Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + ExtraParamLength;
128 ExFreePool(OutputBuf);
129 return STATUS_SUCCESS;
130 }
131 else
132 {
133 ExFreePool(OutputBuf);
134 return STATUS_BUFFER_TOO_SMALL;
135 }
136 }
137 else
138 {
139 DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, DeviceData->AcpiHandle);
140 return STATUS_UNSUCCESSFUL;
141 }
142 }