[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 ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER *SimpleInt;
32 ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING *SimpleStr;
33
34 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
35 return STATUS_INVALID_PARAMETER;
36
37 Signature = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
38
39 switch (Signature)
40 {
41 case ACPI_EVAL_INPUT_BUFFER_SIGNATURE:
42 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER))
43 return STATUS_INVALID_PARAMETER;
44
45 ParamList.Count = 0;
46 break;
47
48 case ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE:
49 SimpleInt = Irp->AssociatedIrp.SystemBuffer;
50
51 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER))
52 return STATUS_INVALID_PARAMETER;
53
54 ParamList.Count = 1;
55
56 ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT));
57 if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES;
58
59 ParamList.Pointer[0].Type = ACPI_TYPE_INTEGER;
60 ParamList.Pointer[0].Integer.Value = SimpleInt->IntegerArgument;
61 break;
62
63 case ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE:
64 SimpleStr = Irp->AssociatedIrp.SystemBuffer;
65
66 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING))
67 return STATUS_INVALID_PARAMETER;
68
69 ParamList.Count = 1;
70
71 ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT));
72 if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES;
73
74 ParamList.Pointer[0].String.Pointer = (CHAR*)SimpleStr->String;
75 ParamList.Pointer[0].String.Length = SimpleStr->StringLength;
76 break;
77
78 default:
79 DPRINT1("Unsupported input buffer signature: %d\n", Signature);
80 return STATUS_NOT_IMPLEMENTED;
81 }
82
83 Status = AcpiEvaluateObject(DeviceData->AcpiHandle,
84 (CHAR*)EvalInputBuff->MethodName,
85 &ParamList,
86 &RetBuff);
87
88 if (ParamList.Count != 0)
89 ExFreePool(ParamList.Pointer);
90
91 if (ACPI_SUCCESS(Status))
92 {
93 ACPI_OBJECT *Obj = RetBuff.Pointer;
94 ULONG ExtraParamLength;
95
96 /* If we didn't get anything back then we're done */
97 if (!RetBuff.Pointer || RetBuff.Length == 0)
98 return STATUS_SUCCESS;
99
100 switch (Obj->Type)
101 {
102 case ACPI_TYPE_INTEGER:
103 ExtraParamLength = sizeof(ULONG);
104 break;
105
106 case ACPI_TYPE_STRING:
107 ExtraParamLength = Obj->String.Length;
108 break;
109
110 case ACPI_TYPE_BUFFER:
111 ExtraParamLength = Obj->Buffer.Length;
112 break;
113
114 case ACPI_TYPE_PACKAGE:
115 DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
116 return STATUS_UNSUCCESSFUL;
117
118 default:
119 ASSERT(FALSE);
120 return STATUS_UNSUCCESSFUL;
121 }
122
123 /* Enough space for a ULONG is always included */
124 if (ExtraParamLength >= sizeof(ULONG))
125 ExtraParamLength -= sizeof(ULONG);
126 else
127 ExtraParamLength = 0;
128
129 OutputBuf = ExAllocatePool(NonPagedPool, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
130 ExtraParamLength);
131 if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES;
132
133 OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
134 OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT);
135 OutputBuf->Count = 1;
136
137 switch (Obj->Type)
138 {
139 case ACPI_TYPE_INTEGER:
140 ACPI_METHOD_SET_ARGUMENT_INTEGER(OutputBuf->Argument, Obj->Integer.Value);
141 break;
142
143 case ACPI_TYPE_STRING:
144 ACPI_METHOD_SET_ARGUMENT_STRING(OutputBuf->Argument, Obj->String.Pointer);
145 break;
146
147 case ACPI_TYPE_BUFFER:
148 ACPI_METHOD_SET_ARGUMENT_BUFFER(OutputBuf->Argument, Obj->Buffer.Pointer, Obj->Buffer.Length);
149 break;
150
151 case ACPI_TYPE_PACKAGE:
152 DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
153 return STATUS_UNSUCCESSFUL;
154
155 default:
156 ASSERT(FALSE);
157 return STATUS_UNSUCCESSFUL;
158 }
159
160 if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
161 ExtraParamLength)
162 {
163 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
164 ExtraParamLength);
165 Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + ExtraParamLength;
166 ExFreePool(OutputBuf);
167 return STATUS_SUCCESS;
168 }
169 else
170 {
171 ExFreePool(OutputBuf);
172 return STATUS_BUFFER_TOO_SMALL;
173 }
174 }
175 else
176 {
177 DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, DeviceData->AcpiHandle);
178 return STATUS_UNSUCCESSFUL;
179 }
180 }