1 /*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Unit Tests for acpi!Bus_PDO_EvalMethod (IOCTL_ACPI_EVAL_METHOD handler)
5 * COPYRIGHT: Copyright 2024 Dmitry Borisov (di.sean@protonmail.com)
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include <apitest.h>
11
12 #define WIN32_NO_STATUS
13 #include <ndk/rtlfuncs.h>
14
15 #define UNIT_TEST
16 #include <acpi.h>
17
18 #include <acpiioct.h>
19 #include <ntintsafe.h>
20 #include <initguid.h>
21
22 /* TEST DEFINITIONS ***********************************************************/
23
24 #define ok_eq_str_ex(entry, value, expected) \
25 ok(!strcmp(value, expected), \
26 "Line %lu: " #value " = \"%s\", expected \"%s\"\n", (entry)->Line, value, expected)
27
28 #define ok_eq_print_ex(entry, value, expected, spec) \
29 ok((value) == (expected), \
30 "Line %lu: " #value " = " spec ", expected " spec "\n", (entry)->Line, value, expected)
31
32 #define ok_not_print_ex(entry, value, expected, spec) \
33 ok((value) != (expected), \
34 "Line %lu: " #value " = " spec ", expected " spec "\n", (entry)->Line, value, expected)
35
36 #define ok_eq_hex_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "0x%08lx")
37 #define ok_eq_pointer_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "%p")
38 #define ok_eq_int_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "%d")
39 #define ok_eq_uint_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "%u")
40 #define ok_eq_ulong_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "%lu")
41 #define ok_eq_ulonglong_ex(entry, value, expected) ok_eq_print_ex(entry, value, expected, "%I64u")
42
43 #define ok_not_pointer_ex(entry, value, expected) ok_not_print_ex(entry, value, expected, "%p")
44
45 typedef struct _EVAL_TEST_ENTRY
46 {
47 ULONG Line;
48
49 ULONG Flags;
50 #define STM_TEST_FLAG_INVALID_ARG_3_1 (1 << 0 )
51 #define STM_TEST_FLAG_INVALID_ARG_3_2 (1 << 1 )
52 #define STM_TEST_FLAG_INVALID_ARG_3_4 (1 << 2 )
53 #define STM_TEST_FLAG_INVALID_ARG_3_5 (1 << 3 )
54 #define STM_TEST_FLAG_INVALID_SIZE_1 (1 << 4 )
55 #define STM_TEST_FLAG_LARGE_ARG_BUFFER (1 << 5 )
56 #define STM_TEST_FLAG_CHANGE_ARG_COUNT (1 << 6 )
57 #define STM_TEST_FLAG_SUB_IN_BUFFER (1 << 7 )
58 #define STM_TEST_FLAG_SUB_IRP_BUFFER (1 << 8 )
59 #define STM_TEST_FLAG_SET_IN_BUFFER (1 << 9 )
60 #define STM_TEST_FLAG_SET_IRP_BUFFER (1 << 10)
61 #define STM_TEST_FLAG_BAD_ARG_TYPE (1 << 11)
62
63 #define GTM_TEST_FLAG_BAD_SIGNARUTE (1 << 0)
64 #define GTM_TEST_FLAG_BUFFER_HAS_SIGNARUTE (1 << 1)
65 #define GTM_TEST_FLAG_BUFFER_HAS_COUNT (1 << 2)
66 #define GTM_TEST_FLAG_BUFFER_HAS_LENGTH (1 << 3)
67 #define GTM_TEST_FLAG_ARG_HAS_BUFFER_TYPE (1 << 4)
68 #define GTM_TEST_FLAG_ARG_HAS_DATA_LENGTH (1 << 5)
69 #define GTM_TEST_FLAG_INC_OUT_BUFFER (1 << 6)
70 #define GTM_TEST_FLAG_DEC_OUT_BUFFER (1 << 7)
71 #define GTM_TEST_FLAG_SET_OUT_BUFFER (1 << 8)
72
73 #define GTM_TEST_FLAG_METHOD_SUCCESS \
74 (GTM_TEST_FLAG_BUFFER_HAS_SIGNARUTE | \
75 GTM_TEST_FLAG_BUFFER_HAS_COUNT | GTM_TEST_FLAG_BUFFER_HAS_LENGTH | \
76 GTM_TEST_FLAG_ARG_HAS_BUFFER_TYPE | GTM_TEST_FLAG_ARG_HAS_DATA_LENGTH)
77
78 #define DSM_TEST_FLAG_EMPTY_PACKAGE (1 << 0)
79 #define DSM_TEST_FLAG_LARGE_SUB_PACKAGE_BUFFER (1 << 1)
80
81 NTSTATUS Status;
82 ULONG Value;
83 } EVAL_TEST_ENTRY;
84
85 /* KERNEL DEFINITIONS (MOCK) **************************************************/
86
87 #define PAGED_CODE()
88 #define CODE_SEG(...)
89 #define DPRINT(...) do { if (0) DbgPrint(__VA_ARGS__); } while (0)
90 #define DPRINT1(...) do { if (0) DbgPrint(__VA_ARGS__); } while (0)
91
92 typedef struct _IO_STACK_LOCATION
93 {
94 union
95 {
96 struct
97 {
98 ULONG OutputBufferLength;
99 ULONG InputBufferLength;
100 } DeviceIoControl;
101 } Parameters;
102 } IO_STACK_LOCATION, *PIO_STACK_LOCATION;
103
104 typedef struct _IRP
105 {
106 union
107 {
108 PVOID SystemBuffer;
109 } AssociatedIrp;
110 IO_STATUS_BLOCK IoStatus;
111
112 PVOID OutputBuffer;
113 IO_STACK_LOCATION MyStack;
114 } IRP, *PIRP;
115
116 static LONG DrvpBlocksAllocated = 0;
117
118 #define ExAllocatePoolUninitialized ExAllocatePoolWithTag
119 #define NonPagedPool 1
120 static
121 PVOID
ExAllocatePoolWithTag(ULONG PoolType,SIZE_T NumberOfBytes,ULONG Tag)122 ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
123 {
124 PULONG_PTR Mem;
125
126 Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID));
127 Mem[0] = NumberOfBytes;
128 Mem[1] = Tag;
129
130 ++DrvpBlocksAllocated;
131
132 return (PVOID)(Mem + 2);
133 }
134
135 static
136 VOID
ExFreePoolWithTag(PVOID MemPtr,ULONG Tag)137 ExFreePoolWithTag(PVOID MemPtr, ULONG Tag)
138 {
139 PULONG_PTR Mem = MemPtr;
140
141 Mem -= 2;
142 ok(Mem[1] == Tag, "Tag is %lx, expected %lx\n", Tag, Mem[1]);
143 HeapFree(GetProcessHeap(), 0, Mem);
144
145 --DrvpBlocksAllocated;
146 }
147
148 static
149 PIO_STACK_LOCATION
IoGetCurrentIrpStackLocation(PIRP Irp)150 IoGetCurrentIrpStackLocation(PIRP Irp)
151 {
152 return &Irp->MyStack;
153 }
154
155 /* ACPI DEFINITIONS ***********************************************************/
156
157 #include <pshpack1.h>
158 typedef struct _IDE_ACPI_TIMING_MODE_BLOCK
159 {
160 struct
161 {
162 ULONG PioSpeed;
163 ULONG DmaSpeed;
164 } Drive[2];
165
166 ULONG ModeFlags;
167 } IDE_ACPI_TIMING_MODE_BLOCK, *PIDE_ACPI_TIMING_MODE_BLOCK;
168 #include <poppack.h>
169
170 #define STM_ID_BLOCK_SIZE 512
171
172 /* ACPI DEFINITIONS (MOCK) ****************************************************/
173
174 #define FAKE_SB_NAMESPACE_ACPI_HANDLE 0xFF0F0001
175 #define FAKE_INTB_ACPI_HANDLE 0xFF0F0002
176 #define FAKE_INTC_ACPI_HANDLE 0xFF0F0003
177
178 typedef struct _PDO_DEVICE_DATA
179 {
180 HANDLE AcpiHandle;
181 } PDO_DEVICE_DATA, *PPDO_DEVICE_DATA;
182
183 typedef struct _GTM_OBJECT_BUFFER
184 {
185 ACPI_OBJECT Obj;
186 IDE_ACPI_TIMING_MODE_BLOCK TimingMode;
187 } GTM_OBJECT_BUFFER, *PGTM_OBJECT_BUFFER;
188
189 typedef struct _BIF_OBJECT_BUFFER
190 {
191 ACPI_OBJECT Obj;
192 ACPI_OBJECT BatteryInformation[13];
193 CHAR Buffer1[1 + 1];
194 CHAR Buffer2[1 + 1];
195 CHAR Buffer3[4 + 1];
196 CHAR Buffer4[7 + 1];
197 } BIF_OBJECT_BUFFER, *PBIF_OBJECT_BUFFER;
198
199 typedef struct _PCL_OBJECT_BUFFER
200 {
201 ACPI_OBJECT Obj;
202 } PCL_OBJECT_BUFFER, *PPCL_OBJECT_BUFFER;
203
204 typedef struct _PRT_OBJECT_BUFFER
205 {
206 ACPI_OBJECT Obj;
207 ACPI_OBJECT PackageContainer[2];
208 ACPI_OBJECT Package1[4];
209 ACPI_OBJECT Package2[4];
210 } PRT_OBJECT_BUFFER, *PPRT_OBJECT_BUFFER;
211
212 DEFINE_GUID(MY_DSM_GUID,
213 0xB76E0B40, 0x3EC6, 0x4DBD, 0x8A, 0xCB, 0x8B, 0xCA, 0x65, 0xB8, 0xBC, 0x70);
214
215 static const ULONG DrvpBifIntegerFields[9] =
216 {
217 0, 50000, 50000, 1, 10000, 100, 50, 1, 1
218 };
219
220 static const ULONG DrvpMyDsmIntegerFields[3] =
221 {
222 0xAAAAAAAA, 0xBBBBBBBB, 0xDDDDDDDD
223 };
224
225 static const EVAL_TEST_ENTRY* DrvpEvalTestEntry;
226
227 void *
AcpiOsAllocate(ACPI_SIZE Size)228 AcpiOsAllocate (
229 ACPI_SIZE Size)
230 {
231 return ExAllocatePoolWithTag(NonPagedPool, Size, 'FFUB');
232 }
233
234 void
AcpiOsFree(void * Memory)235 AcpiOsFree (
236 void * Memory)
237 {
238 ExFreePoolWithTag(Memory, 'FFUB');
239 }
240
241 ACPI_STATUS
AcpiGetName(ACPI_HANDLE Handle,UINT32 NameType,ACPI_BUFFER * Buffer)242 AcpiGetName (
243 ACPI_HANDLE Handle,
244 UINT32 NameType,
245 ACPI_BUFFER *Buffer)
246 {
247 /* We don't support anything else */
248 ok(NameType == ACPI_SINGLE_NAME, "Unexpected call to %s\n", __FUNCTION__);
249
250 /* Return a NULL-terminated string */
251 if (Buffer->Length < (4 + 1))
252 return AE_BUFFER_OVERFLOW;
253
254 switch ((ULONG_PTR)Handle)
255 {
256 case FAKE_SB_NAMESPACE_ACPI_HANDLE:
257 RtlCopyMemory(Buffer->Pointer, "_SB_", sizeof("_SB_"));
258 break;
259
260 case FAKE_INTB_ACPI_HANDLE:
261 RtlCopyMemory(Buffer->Pointer, "LNKB", sizeof("LNKB"));
262 break;
263
264 case FAKE_INTC_ACPI_HANDLE:
265 RtlCopyMemory(Buffer->Pointer, "LNKC", sizeof("LNKC"));
266 break;
267
268 default:
269 return AE_BAD_PARAMETER;
270 }
271
272 return AE_OK;
273 }
274
275 ACPI_STATUS
AcpiEvaluateObject(ACPI_HANDLE Object,ACPI_STRING Pathname,ACPI_OBJECT_LIST * ParameterObjects,ACPI_BUFFER * ReturnObjectBuffer)276 AcpiEvaluateObject (
277 ACPI_HANDLE Object,
278 ACPI_STRING Pathname,
279 ACPI_OBJECT_LIST *ParameterObjects,
280 ACPI_BUFFER *ReturnObjectBuffer)
281 {
282 UNREFERENCED_PARAMETER(Object);
283
284 /* We don't support anything else */
285 ok(ReturnObjectBuffer->Length == ACPI_ALLOCATE_BUFFER,
286 "Unexpected call to %s\n", __FUNCTION__);
287
288 if (strcmp(Pathname, "_STM") == 0)
289 {
290 ACPI_OBJECT* Arg;
291 PIDE_ACPI_TIMING_MODE_BLOCK TimingMode;
292
293 if (ParameterObjects->Count > 3)
294 return AE_AML_UNINITIALIZED_ARG;
295
296 if (ParameterObjects->Count != 3)
297 return AE_OK;
298
299 /* Argument 1 */
300 {
301 Arg = ParameterObjects->Pointer;
302
303 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_BUFFER);
304 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Buffer.Length, sizeof(*TimingMode));
305
306 TimingMode = (PIDE_ACPI_TIMING_MODE_BLOCK)Arg->Buffer.Pointer;
307
308 ok_eq_ulong_ex(DrvpEvalTestEntry, TimingMode->Drive[0].PioSpeed, 508LU);
309 ok_eq_ulong_ex(DrvpEvalTestEntry, TimingMode->Drive[0].DmaSpeed, 120LU);
310 ok_eq_ulong_ex(DrvpEvalTestEntry, TimingMode->Drive[1].PioSpeed, 240LU);
311 ok_eq_ulong_ex(DrvpEvalTestEntry, TimingMode->Drive[1].DmaSpeed, 180LU);
312 ok_eq_hex_ex(DrvpEvalTestEntry, TimingMode->ModeFlags, 0x10LU);
313 }
314 /* Argument 2 */
315 {
316 ++Arg;
317
318 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_BUFFER);
319 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Buffer.Length, STM_ID_BLOCK_SIZE);
320 }
321 /* Argument 3 */
322 {
323 ++Arg;
324
325 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_BUFFER);
326 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Buffer.Length, STM_ID_BLOCK_SIZE);
327 }
328
329 return AE_OK;
330 }
331 else if (strcmp(Pathname, "_GTM") == 0)
332 {
333 PGTM_OBJECT_BUFFER ReturnObject;
334 PIDE_ACPI_TIMING_MODE_BLOCK TimingMode;
335
336 ReturnObject = AcpiOsAllocate(sizeof(*ReturnObject));
337 if (!ReturnObject)
338 return AE_NO_MEMORY;
339
340 /*
341 * VPC 2007 output
342 * AcpiGetHandle(NULL, "\\_SB.PCI0.IDE0.CHN1", &ObjHandle);
343 * AcpiEvaluateObject(ObjHandle, "_GTM", NULL, &ReturnObj);
344 */
345 TimingMode = &ReturnObject->TimingMode;
346 TimingMode->Drive[0].PioSpeed = 900;
347 TimingMode->Drive[0].DmaSpeed = 900;
348 TimingMode->Drive[1].PioSpeed = 120;
349 TimingMode->Drive[1].DmaSpeed = 120;
350 TimingMode->ModeFlags = 0x12;
351
352 ReturnObject->Obj.Type = ACPI_TYPE_BUFFER;
353 ReturnObject->Obj.Buffer.Length = sizeof(*TimingMode);
354 ReturnObject->Obj.Buffer.Pointer = (PUCHAR)TimingMode;
355
356 ReturnObjectBuffer->Pointer = ReturnObject;
357 ReturnObjectBuffer->Length = sizeof(*ReturnObject);
358 return AE_OK;
359 }
360 else if (strcmp(Pathname, "_BIF") == 0)
361 {
362 PBIF_OBJECT_BUFFER ReturnObject;
363 ACPI_OBJECT* BatteryInformation;
364 ULONG i;
365
366 ReturnObject = AcpiOsAllocate(sizeof(*ReturnObject));
367 if (!ReturnObject)
368 return AE_NO_MEMORY;
369
370 /*
371 * Vbox 7.0 output
372 * AcpiGetHandle(NULL, "\\_SB.PCI0.BAT0", &ObjHandle);
373 * AcpiEvaluateObject(ObjHandle, "_BIF", NULL, &ReturnObj);
374 */
375 BatteryInformation = &ReturnObject->BatteryInformation[0];
376 for (i = 0; i < RTL_NUMBER_OF(DrvpBifIntegerFields); ++i)
377 {
378 BatteryInformation[i].Integer.Type = ACPI_TYPE_INTEGER;
379 BatteryInformation[i].Integer.Value = DrvpBifIntegerFields[i];
380 }
381 BatteryInformation[i].String.Type = ACPI_TYPE_STRING;
382 BatteryInformation[i].String.Length = 1; /* Excluding the trailing null */
383 BatteryInformation[i].String.Pointer = &ReturnObject->Buffer1[0];
384 RtlCopyMemory(BatteryInformation[i].String.Pointer, "1", sizeof("1"));
385 ++i;
386 BatteryInformation[i].String.Type = ACPI_TYPE_STRING;
387 BatteryInformation[i].String.Length = 1;
388 BatteryInformation[i].String.Pointer = &ReturnObject->Buffer2[0];
389 RtlCopyMemory(BatteryInformation[i].String.Pointer, "0", sizeof("0"));
390 ++i;
391 BatteryInformation[i].String.Type = ACPI_TYPE_STRING;
392 BatteryInformation[i].String.Length = 4;
393 BatteryInformation[i].String.Pointer = &ReturnObject->Buffer3[0];
394 RtlCopyMemory(BatteryInformation[i].String.Pointer, "VBOX", sizeof("VBOX"));
395 ++i;
396 BatteryInformation[i].String.Type = ACPI_TYPE_STRING;
397 BatteryInformation[i].String.Length = 7;
398 BatteryInformation[i].String.Pointer = &ReturnObject->Buffer4[0];
399 RtlCopyMemory(BatteryInformation[i].String.Pointer, "innotek", sizeof("innotek"));
400
401 ReturnObject->Obj.Type = ACPI_TYPE_PACKAGE;
402 ReturnObject->Obj.Package.Count = 13;
403 ReturnObject->Obj.Package.Elements = BatteryInformation;
404
405 ReturnObjectBuffer->Pointer = ReturnObject;
406 ReturnObjectBuffer->Length = sizeof(*ReturnObject);
407 return AE_OK;
408 }
409 else if (strcmp(Pathname, "_PCL") == 0)
410 {
411 PPCL_OBJECT_BUFFER ReturnObject;
412
413 ReturnObject = AcpiOsAllocate(sizeof(*ReturnObject));
414 if (!ReturnObject)
415 return AE_NO_MEMORY;
416
417 /*
418 * Vbox 7.0 output
419 * AcpiGetHandle(NULL, "\\_SB.PCI0.AC", &ObjHandle);
420 * AcpiEvaluateObject(ObjHandle, "_PCL", NULL, &ReturnObj);
421 */
422 ReturnObject->Obj.Reference.Type = ACPI_TYPE_LOCAL_REFERENCE;
423 ReturnObject->Obj.Reference.ActualType = ACPI_TYPE_DEVICE;
424 ReturnObject->Obj.Reference.Handle = (ACPI_HANDLE)(ULONG_PTR)FAKE_SB_NAMESPACE_ACPI_HANDLE;
425
426 ReturnObjectBuffer->Pointer = ReturnObject;
427 ReturnObjectBuffer->Length = sizeof(*ReturnObject);
428 return AE_OK;
429 }
430 else if (strcmp(Pathname, "_PRT") == 0)
431 {
432 PPRT_OBJECT_BUFFER ReturnObject;
433 ULONG i;
434
435 ReturnObject = AcpiOsAllocate(sizeof(*ReturnObject));
436 if (!ReturnObject)
437 return AE_NO_MEMORY;
438
439 /*
440 * Vbox 7.0 output
441 * AcpiGetHandle(NULL, "\\_SB.PCI0", &ObjHandle);
442 * AcpiEvaluateObject(ObjHandle, "_PRT", NULL, &ReturnObj);
443 *
444 * NOTE: To avoid similar copies of code executed and tested over and over again
445 * we return 2 packages. The original method returns 120 packages.
446 */
447 ReturnObject->Obj.Type = ACPI_TYPE_PACKAGE;
448 ReturnObject->Obj.Package.Count = 2;
449 ReturnObject->Obj.Package.Elements = &ReturnObject->PackageContainer[0];
450
451 i = 0;
452 ReturnObject->PackageContainer[i].Type = ACPI_TYPE_PACKAGE;
453 ReturnObject->PackageContainer[i].Package.Count = 4;
454 ReturnObject->PackageContainer[i].Package.Elements = &ReturnObject->Package1[0];
455 ++i;
456 ReturnObject->PackageContainer[i].Type = ACPI_TYPE_PACKAGE;
457 ReturnObject->PackageContainer[i].Package.Count = 4;
458 ReturnObject->PackageContainer[i].Package.Elements = &ReturnObject->Package2[0];
459
460 /* Package 1 */
461 i = 0;
462 ReturnObject->Package1[i].Integer.Type = ACPI_TYPE_INTEGER;
463 ReturnObject->Package1[i].Integer.Value = 0x0002FFFF;
464 ++i;
465 ReturnObject->Package1[i].Integer.Type = ACPI_TYPE_INTEGER;
466 ReturnObject->Package1[i].Integer.Value = 0x00000000;
467 ++i;
468 ReturnObject->Package1[i].Reference.Type = ACPI_TYPE_LOCAL_REFERENCE;
469 ReturnObject->Package1[i].Reference.ActualType = ACPI_TYPE_DEVICE;
470 ReturnObject->Package1[i].Reference.Handle = (ACPI_HANDLE)(ULONG_PTR)FAKE_INTB_ACPI_HANDLE;
471 ++i;
472 ReturnObject->Package1[i].Integer.Type = ACPI_TYPE_INTEGER;
473 ReturnObject->Package1[i].Integer.Value = 0x00000000;
474
475 /* Package 2 */
476 i = 0;
477 ReturnObject->Package2[i].Integer.Type = ACPI_TYPE_INTEGER;
478 ReturnObject->Package2[i].Integer.Value = 0x0002FFFF;
479 ++i;
480 ReturnObject->Package2[i].Integer.Type = ACPI_TYPE_INTEGER;
481 ReturnObject->Package2[i].Integer.Value = 0x00000001;
482 ++i;
483 ReturnObject->Package2[i].Reference.Type = ACPI_TYPE_LOCAL_REFERENCE;
484 ReturnObject->Package2[i].Reference.ActualType = ACPI_TYPE_DEVICE;
485 ReturnObject->Package2[i].Reference.Handle = (ACPI_HANDLE)(ULONG_PTR)FAKE_INTC_ACPI_HANDLE;
486 ++i;
487 ReturnObject->Package2[i].Integer.Type = ACPI_TYPE_INTEGER;
488 ReturnObject->Package2[i].Integer.Value = 0x00000000;
489
490 ReturnObjectBuffer->Pointer = ReturnObject;
491 ReturnObjectBuffer->Length = sizeof(*ReturnObject);
492 return AE_OK;
493 }
494 else if (strcmp(Pathname, "_DSM") == 0)
495 {
496 ACPI_OBJECT* Arg;
497
498 /* Assumed object count per the spec */
499 ok_eq_uint(ParameterObjects->Count, 4);
500
501 if (ParameterObjects->Count != 4)
502 return AE_AML_UNINITIALIZED_ARG;
503
504 /* Argument 1 */
505 {
506 Arg = ParameterObjects->Pointer;
507
508 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_BUFFER);
509 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Buffer.Length, sizeof(GUID));
510 }
511
512 /* NOTE: This UUID doesn't exist, for testing purposes only */
513 if (IsEqualGUID(Arg->Buffer.Pointer, &MY_DSM_GUID))
514 {
515 /* Argument 2 */
516 {
517 ++Arg;
518
519 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_INTEGER);
520 ok_eq_ulonglong_ex(DrvpEvalTestEntry, Arg->Integer.Value, 1ULL);
521 }
522 /* Argument 3 */
523 {
524 ++Arg;
525
526 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_INTEGER);
527 ok_eq_ulonglong_ex(DrvpEvalTestEntry, Arg->Integer.Value, 2ULL);
528 }
529 /* Argument 4 */
530 {
531 ++Arg;
532
533 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_PACKAGE);
534
535 if (DrvpEvalTestEntry->Flags & DSM_TEST_FLAG_EMPTY_PACKAGE)
536 {
537 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Package.Count, 0);
538 ok_eq_pointer_ex(DrvpEvalTestEntry, Arg->Package.Elements, NULL);
539 }
540 else
541 {
542 ACPI_OBJECT* PackageArg;
543 ACPI_OBJECT* PackageArg2;
544 ULONG i;
545
546 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Package.Count, 4);
547 ok_not_pointer_ex(DrvpEvalTestEntry, Arg->Package.Elements, NULL);
548
549 if (!Arg->Package.Elements)
550 return AE_AML_UNINITIALIZED_ARG;
551
552 /* Package 1 Arguments 1-2 */
553 PackageArg = Arg->Package.Elements;
554 for (i = 0; i < RTL_NUMBER_OF(DrvpMyDsmIntegerFields) - 1; i++)
555 {
556 ok_eq_uint_ex(DrvpEvalTestEntry, PackageArg->Type, ACPI_TYPE_INTEGER);
557 ok_eq_ulonglong_ex(DrvpEvalTestEntry,
558 PackageArg->Integer.Value,
559 (ULONG64)DrvpMyDsmIntegerFields[i]);
560
561 ++PackageArg;
562 }
563
564 /* Package 1 Argument 3 */
565 {
566 Arg = PackageArg;
567
568 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Type, ACPI_TYPE_PACKAGE);
569 ok_eq_uint_ex(DrvpEvalTestEntry, Arg->Package.Count, 1);
570
571 /* Package 2 Argument 1 */
572 PackageArg2 = Arg->Package.Elements;
573
574 ok_eq_uint_ex(DrvpEvalTestEntry, PackageArg2->Type, ACPI_TYPE_STRING);
575
576 /* Excluding the trailing null */
577 ok_eq_uint_ex(DrvpEvalTestEntry,
578 PackageArg2->String.Length,
579 (sizeof("1_TESTDATATESTDATA_2") - 1));
580 ok_eq_int_ex(DrvpEvalTestEntry,
581 memcmp(PackageArg2->String.Pointer,
582 "1_TESTDATATESTDATA_2",
583 sizeof("1_TESTDATATESTDATA_2") - 1),
584 0);
585 }
586 /* Package 1 Argument 4 */
587 {
588 ++PackageArg;
589
590 ok_eq_uint_ex(DrvpEvalTestEntry, PackageArg->Type, ACPI_TYPE_INTEGER);
591 ok_eq_ulonglong_ex(DrvpEvalTestEntry,
592 PackageArg->Integer.Value,
593 (ULONG64)DrvpMyDsmIntegerFields[2]);
594 }
595 }
596 }
597
598 return AE_OK;
599 }
600 }
601
602 return AE_NOT_FOUND;
603 }
604
605 #include "../../../../drivers/bus/acpi/eval.c"
606
607 /* GLOBALS ********************************************************************/
608
609 /* 2 ID blocks + timings + room for the test data */
610 #define STM_MAX_BUFFER_SIZE \
611 (FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX, Argument) + \
612 2 * STM_ID_BLOCK_SIZE + sizeof(IDE_ACPI_TIMING_MODE_BLOCK) + 0x100)
613
614 #define GTM_MAX_BUFFER_SIZE \
615 (FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + \
616 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(IDE_ACPI_TIMING_MODE_BLOCK)) + 0x50)
617
618 static const EVAL_TEST_ENTRY DrvpSmtTests[] =
619 {
620 { __LINE__, 0, STATUS_SUCCESS },
621 { __LINE__, STM_TEST_FLAG_INVALID_SIZE_1, STATUS_ACPI_INVALID_ARGTYPE },
622 { __LINE__, STM_TEST_FLAG_LARGE_ARG_BUFFER, STATUS_ACPI_INVALID_ARGTYPE },
623 { __LINE__, STM_TEST_FLAG_SUB_IN_BUFFER, STATUS_SUCCESS, 1 },
624 { __LINE__, STM_TEST_FLAG_SUB_IN_BUFFER, STATUS_SUCCESS, 9 },
625 { __LINE__, STM_TEST_FLAG_SUB_IRP_BUFFER, STATUS_SUCCESS, 1 },
626 { __LINE__, STM_TEST_FLAG_SUB_IRP_BUFFER, STATUS_SUCCESS, 9 },
627 { __LINE__, STM_TEST_FLAG_SET_IN_BUFFER, STATUS_SUCCESS, 0 },
628 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH, 0 },
629 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH,
630 RTL_SIZEOF_THROUGH_FIELD(ACPI_EVAL_INPUT_BUFFER, Signature) - 2 },
631 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH,
632 RTL_SIZEOF_THROUGH_FIELD(ACPI_EVAL_INPUT_BUFFER, Signature) - 1 },
633 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH,
634 RTL_SIZEOF_THROUGH_FIELD(ACPI_EVAL_INPUT_BUFFER, Signature) },
635 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH,
636 sizeof(ACPI_EVAL_INPUT_BUFFER) - 2 },
637 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INFO_LENGTH_MISMATCH,
638 sizeof(ACPI_EVAL_INPUT_BUFFER) - 1 },
639 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INSUFFICIENT_RESOURCES,
640 sizeof(ACPI_EVAL_INPUT_BUFFER) },
641 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INSUFFICIENT_RESOURCES,
642 sizeof(ACPI_EVAL_INPUT_BUFFER) + 1 },
643 { __LINE__, STM_TEST_FLAG_SET_IRP_BUFFER, STATUS_INSUFFICIENT_RESOURCES,
644 sizeof(ACPI_EVAL_INPUT_BUFFER) + 2 },
645 { __LINE__, STM_TEST_FLAG_BAD_ARG_TYPE, STATUS_SUCCESS, 0 },
646 { __LINE__, STM_TEST_FLAG_CHANGE_ARG_COUNT, STATUS_ACPI_INCORRECT_ARGUMENT_COUNT, 0 },
647
648 #if 0
649 /*
650 * The return status depends on AML interpreter implementation
651 * and testing it is not practical, keeping this for reference only.
652 */
653 { __LINE__, STM_TEST_FLAG_INVALID_ARG_3_1, STATUS_SUCCESS },
654 { __LINE__, STM_TEST_FLAG_INVALID_ARG_3_2, STATUS_ACPI_INVALID_ARGTYPE },
655 { __LINE__, STM_TEST_FLAG_INVALID_ARG_3_4, STATUS_SUCCESS },
656 { __LINE__, STM_TEST_FLAG_INVALID_ARG_3_5, STATUS_SUCCESS },
657 { __LINE__, STM_TEST_FLAG_CHANGE_ARG_COUNT, STATUS_ACPI_INCORRECT_ARGUMENT_COUNT, 30 },
658 { __LINE__, STM_TEST_FLAG_CHANGE_ARG_COUNT, STATUS_ACPI_INCORRECT_ARGUMENT_COUNT, 2 },
659 #endif
660 };
661
662 static const EVAL_TEST_ENTRY DrvpGtmTests[] =
663 {
664 { __LINE__, GTM_TEST_FLAG_METHOD_SUCCESS, STATUS_SUCCESS },
665 { __LINE__, GTM_TEST_FLAG_METHOD_SUCCESS |
666 GTM_TEST_FLAG_INC_OUT_BUFFER, STATUS_SUCCESS, 1 },
667 { __LINE__, GTM_TEST_FLAG_METHOD_SUCCESS |
668 GTM_TEST_FLAG_DEC_OUT_BUFFER, STATUS_BUFFER_OVERFLOW, 1 },
669 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_SUCCESS, 0 },
670 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_BUFFER_TOO_SMALL, 1 },
671 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_BUFFER_TOO_SMALL,
672 FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) - 1 },
673 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_BUFFER_TOO_SMALL,
674 FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) },
675 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_BUFFER_TOO_SMALL,
676 FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + 1 },
677 { __LINE__, GTM_TEST_FLAG_SET_OUT_BUFFER, STATUS_BUFFER_TOO_SMALL,
678 sizeof(ACPI_EVAL_OUTPUT_BUFFER) - 1 },
679 { __LINE__, GTM_TEST_FLAG_BUFFER_HAS_SIGNARUTE |
680 GTM_TEST_FLAG_BUFFER_HAS_COUNT |
681 GTM_TEST_FLAG_BUFFER_HAS_LENGTH |
682 GTM_TEST_FLAG_SET_OUT_BUFFER,
683 STATUS_BUFFER_OVERFLOW,
684 sizeof(ACPI_EVAL_OUTPUT_BUFFER) },
685 { __LINE__, GTM_TEST_FLAG_BUFFER_HAS_SIGNARUTE |
686 GTM_TEST_FLAG_BUFFER_HAS_COUNT |
687 GTM_TEST_FLAG_BUFFER_HAS_LENGTH |
688 GTM_TEST_FLAG_SET_OUT_BUFFER,
689 STATUS_BUFFER_OVERFLOW,
690 sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 1 },
691
692 /* Pass an invalid signature */
693 { __LINE__, GTM_TEST_FLAG_BAD_SIGNARUTE, STATUS_INVALID_PARAMETER_1 },
694 { __LINE__, GTM_TEST_FLAG_BAD_SIGNARUTE | GTM_TEST_FLAG_SET_OUT_BUFFER,
695 STATUS_INVALID_PARAMETER_1, 0 },
696 { __LINE__, GTM_TEST_FLAG_BAD_SIGNARUTE | GTM_TEST_FLAG_SET_OUT_BUFFER,
697 STATUS_BUFFER_TOO_SMALL,
698 sizeof(ACPI_EVAL_OUTPUT_BUFFER) - 1 },
699 { __LINE__, GTM_TEST_FLAG_BAD_SIGNARUTE | GTM_TEST_FLAG_SET_OUT_BUFFER,
700 STATUS_INVALID_PARAMETER_1,
701 sizeof(ACPI_EVAL_OUTPUT_BUFFER) },
702 };
703
704 static const EVAL_TEST_ENTRY DrvpBifTests[] =
705 {
706 { __LINE__, 0, STATUS_SUCCESS },
707 };
708
709 static const EVAL_TEST_ENTRY DrvpPclTests[] =
710 {
711 { __LINE__, 0, STATUS_SUCCESS },
712 };
713
714 static const EVAL_TEST_ENTRY DrvpPrtTests[] =
715 {
716 { __LINE__, 0, STATUS_SUCCESS },
717 };
718
719 static const EVAL_TEST_ENTRY DrvpDsmTests[] =
720 {
721 { __LINE__, 0, STATUS_SUCCESS },
722 { __LINE__, DSM_TEST_FLAG_EMPTY_PACKAGE, STATUS_SUCCESS },
723 { __LINE__, DSM_TEST_FLAG_LARGE_SUB_PACKAGE_BUFFER, STATUS_ACPI_INVALID_ARGTYPE },
724 };
725
726 /* FUNCTIONS ******************************************************************/
727
728 static
729 NTSTATUS
DrvCallAcpiDriver(_In_ PVOID InputBuffer,_In_ ULONG InputBufferLength,_Out_opt_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,_In_ ULONG OutputBufferLength)730 DrvCallAcpiDriver(
731 _In_ PVOID InputBuffer,
732 _In_ ULONG InputBufferLength,
733 _Out_opt_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,
734 _In_ ULONG OutputBufferLength)
735 {
736 PDO_DEVICE_DATA DeviceData;
737 IRP Irp;
738
739 DeviceData.AcpiHandle = NULL;
740
741 Irp.AssociatedIrp.SystemBuffer = InputBuffer;
742 Irp.OutputBuffer = OutputBuffer;
743
744 Irp.MyStack.Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
745 Irp.MyStack.Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
746
747 return Bus_PDO_EvalMethod(&DeviceData, &Irp);
748 }
749
750 static
751 VOID
DrvEvaluateStmObject(_In_ const EVAL_TEST_ENTRY * TestEntry,_In_ PIDE_ACPI_TIMING_MODE_BLOCK TimingMode,_In_ PUCHAR IdBlock,_In_ PACPI_EVAL_INPUT_BUFFER_COMPLEX InputBuffer)752 DrvEvaluateStmObject(
753 _In_ const EVAL_TEST_ENTRY* TestEntry,
754 _In_ PIDE_ACPI_TIMING_MODE_BLOCK TimingMode,
755 _In_ PUCHAR IdBlock,
756 _In_ PACPI_EVAL_INPUT_BUFFER_COMPLEX InputBuffer)
757 {
758 PACPI_METHOD_ARGUMENT Argument, Argument2, Argument3;
759 NTSTATUS Status;
760 ULONG InputBufferSize, IrpBufferSize;
761
762 InputBufferSize = FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX, Argument) +
763 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(*TimingMode)) +
764 ACPI_METHOD_ARGUMENT_LENGTH(STM_ID_BLOCK_SIZE) +
765 ACPI_METHOD_ARGUMENT_LENGTH(STM_ID_BLOCK_SIZE);
766
767 if (TestEntry->Flags & STM_TEST_FLAG_INVALID_SIZE_1)
768 {
769 InputBufferSize -= ACPI_METHOD_ARGUMENT_LENGTH(STM_ID_BLOCK_SIZE) +
770 ACPI_METHOD_ARGUMENT_LENGTH(STM_ID_BLOCK_SIZE);
771 }
772
773 InputBuffer->MethodNameAsUlong = 'MTS_'; // _STM
774 InputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
775 if (TestEntry->Flags & STM_TEST_FLAG_SUB_IN_BUFFER)
776 {
777 InputBuffer->Size = InputBufferSize - TestEntry->Value;
778 }
779 else if (TestEntry->Flags & STM_TEST_FLAG_SET_IN_BUFFER)
780 {
781 InputBuffer->Size = TestEntry->Value;
782 }
783 else
784 {
785 InputBuffer->Size = InputBufferSize;
786 }
787
788 if (TestEntry->Flags & STM_TEST_FLAG_CHANGE_ARG_COUNT)
789 {
790 InputBuffer->ArgumentCount = TestEntry->Value;
791 }
792 else
793 {
794 InputBuffer->ArgumentCount = 3;
795 }
796
797 /* Argument 1: The channel timing information block */
798 Argument = InputBuffer->Argument;
799 ACPI_METHOD_SET_ARGUMENT_BUFFER(Argument, TimingMode, sizeof(*TimingMode));
800
801 /* Argument 2: The ATA drive ID block */
802 Argument2 = ACPI_METHOD_NEXT_ARGUMENT(Argument);
803 ACPI_METHOD_SET_ARGUMENT_BUFFER(Argument2, IdBlock, STM_ID_BLOCK_SIZE);
804
805 /* Argument 3: The ATA drive ID block */
806 Argument3 = ACPI_METHOD_NEXT_ARGUMENT(Argument2);
807 ACPI_METHOD_SET_ARGUMENT_BUFFER(Argument3, IdBlock, STM_ID_BLOCK_SIZE);
808
809 if (TestEntry->Flags & STM_TEST_FLAG_BAD_ARG_TYPE)
810 {
811 Argument3->Type = 0xFFFF;
812 }
813
814 if (TestEntry->Flags & STM_TEST_FLAG_LARGE_ARG_BUFFER)
815 {
816 Argument2->DataLength = STM_ID_BLOCK_SIZE * 2;
817 Argument3->DataLength = STM_ID_BLOCK_SIZE * 2;
818 }
819
820 if (TestEntry->Flags & STM_TEST_FLAG_INVALID_ARG_3_1)
821 {
822 ACPI_METHOD_SET_ARGUMENT_STRING(Argument3, IdBlock);
823 }
824 else if (TestEntry->Flags & STM_TEST_FLAG_INVALID_ARG_3_2)
825 {
826 ACPI_METHOD_SET_ARGUMENT_INTEGER(Argument3, 0xDEADBEEF);
827 }
828 else if (TestEntry->Flags & STM_TEST_FLAG_INVALID_ARG_3_4)
829 {
830 Argument3->DataLength += 5;
831 }
832 else if (TestEntry->Flags & STM_TEST_FLAG_INVALID_ARG_3_5)
833 {
834 Argument3->DataLength -= 5;
835 }
836
837 if (TestEntry->Flags & STM_TEST_FLAG_SUB_IRP_BUFFER)
838 {
839 IrpBufferSize = InputBufferSize - TestEntry->Value;
840 }
841 else if (TestEntry->Flags & STM_TEST_FLAG_SET_IRP_BUFFER)
842 {
843 IrpBufferSize = TestEntry->Value;
844 }
845 else
846 {
847 IrpBufferSize = InputBufferSize;
848 }
849
850 /* Evaluate the _STM method */
851 DrvpEvalTestEntry = TestEntry;
852 Status = DrvCallAcpiDriver(InputBuffer, IrpBufferSize, NULL, 0);
853
854 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
855 }
856
857 static
858 VOID
DrvTestComplexBuffer(VOID)859 DrvTestComplexBuffer(VOID)
860 {
861 IDE_ACPI_TIMING_MODE_BLOCK TimingMode;
862 UCHAR IdBlock[STM_ID_BLOCK_SIZE];
863 ULONG i;
864 UCHAR Buffer[STM_MAX_BUFFER_SIZE];
865 PACPI_EVAL_INPUT_BUFFER_COMPLEX InputBuffer = (PACPI_EVAL_INPUT_BUFFER_COMPLEX)Buffer;
866
867 /* Initialize method arguments */
868 RtlZeroMemory(IdBlock, sizeof(IdBlock));
869 TimingMode.Drive[0].PioSpeed = 508;
870 TimingMode.Drive[0].DmaSpeed = 120;
871 TimingMode.Drive[1].PioSpeed = 240;
872 TimingMode.Drive[1].DmaSpeed = 180;
873 TimingMode.ModeFlags = 0x10;
874
875 for (i = 0; i < RTL_NUMBER_OF(DrvpSmtTests); ++i)
876 {
877 DrvEvaluateStmObject(&DrvpSmtTests[i], &TimingMode, IdBlock, InputBuffer);
878 }
879 }
880
881 static
882 VOID
DrvEvaluateGtmObject(_In_ const EVAL_TEST_ENTRY * TestEntry,_In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)883 DrvEvaluateGtmObject(
884 _In_ const EVAL_TEST_ENTRY* TestEntry,
885 _In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)
886 {
887 ACPI_EVAL_INPUT_BUFFER InputBuffer;
888 ULONG OutputBufferSize;
889 NTSTATUS Status;
890 PACPI_METHOD_ARGUMENT Argument;
891 ULONG Signature, Count, Length;
892 USHORT Type, DataLength;
893 PIDE_ACPI_TIMING_MODE_BLOCK TimingMode;
894
895 InputBuffer.MethodNameAsUlong = 'MTG_'; // _GTM
896 if (TestEntry->Flags & GTM_TEST_FLAG_BAD_SIGNARUTE)
897 InputBuffer.Signature = 'BAD0';
898 else
899 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
900
901 OutputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
902 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(*TimingMode));
903
904 if (TestEntry->Flags & GTM_TEST_FLAG_INC_OUT_BUFFER)
905 {
906 OutputBufferSize += TestEntry->Value;
907 }
908 else if (TestEntry->Flags & GTM_TEST_FLAG_DEC_OUT_BUFFER)
909 {
910 OutputBufferSize -= TestEntry->Value;
911 }
912 else if (TestEntry->Flags & GTM_TEST_FLAG_SET_OUT_BUFFER)
913 {
914 OutputBufferSize = TestEntry->Value;
915 }
916
917 /* Evaluate the _GTM method */
918 Status = DrvCallAcpiDriver(&InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputBufferSize);
919
920 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
921
922 if (TestEntry->Flags & GTM_TEST_FLAG_BUFFER_HAS_SIGNARUTE)
923 Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
924 else
925 Signature = 0;
926 ok_eq_hex_ex(TestEntry, OutputBuffer->Signature, Signature);
927
928 if (TestEntry->Flags & GTM_TEST_FLAG_BUFFER_HAS_COUNT)
929 Count = 1;
930 else
931 Count = 0;
932 ok_eq_ulong_ex(TestEntry, OutputBuffer->Count, Count);
933
934 if (TestEntry->Flags & GTM_TEST_FLAG_BUFFER_HAS_LENGTH)
935 {
936 Length = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
937 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(*TimingMode));
938 }
939 else
940 {
941 Length = 0;
942 }
943 ok_eq_ulong_ex(TestEntry, OutputBuffer->Length, Length);
944
945 Argument = OutputBuffer->Argument;
946 if (TestEntry->Flags & GTM_TEST_FLAG_ARG_HAS_BUFFER_TYPE)
947 Type = ACPI_METHOD_ARGUMENT_BUFFER;
948 else
949 Type = ACPI_METHOD_ARGUMENT_INTEGER;
950 ok_eq_uint_ex(TestEntry, Argument->Type, Type);
951
952 if (TestEntry->Flags & GTM_TEST_FLAG_ARG_HAS_DATA_LENGTH)
953 DataLength = sizeof(ACPI_EVAL_OUTPUT_BUFFER);
954 else
955 DataLength = 0;
956 ok_eq_uint_ex(TestEntry, Argument->DataLength, DataLength);
957
958 if ((TestEntry->Flags & GTM_TEST_FLAG_ARG_HAS_BUFFER_TYPE) && NT_SUCCESS(TestEntry->Status))
959 {
960 TimingMode = (PIDE_ACPI_TIMING_MODE_BLOCK)Argument->Data;
961
962 ok_eq_ulong_ex(TestEntry, TimingMode->Drive[0].PioSpeed, 900LU);
963 ok_eq_ulong_ex(TestEntry, TimingMode->Drive[0].DmaSpeed, 900LU);
964 ok_eq_ulong_ex(TestEntry, TimingMode->Drive[1].PioSpeed, 120LU);
965 ok_eq_ulong_ex(TestEntry, TimingMode->Drive[1].DmaSpeed, 120LU);
966 ok_eq_hex_ex(TestEntry, TimingMode->ModeFlags, 0x12LU);
967 }
968 }
969
970 static
971 VOID
DrvTestInputBuffer(VOID)972 DrvTestInputBuffer(VOID)
973 {
974 UCHAR Buffer[GTM_MAX_BUFFER_SIZE];
975 ULONG i;
976 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)Buffer;
977
978 for (i = 0; i < RTL_NUMBER_OF(DrvpGtmTests); ++i)
979 {
980 RtlZeroMemory(Buffer, sizeof(Buffer));
981
982 DrvEvaluateGtmObject(&DrvpGtmTests[i], OutputBuffer);
983 }
984 }
985
986 static
987 VOID
DrvEvaluateBifObject(_In_ const EVAL_TEST_ENTRY * TestEntry,_In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)988 DrvEvaluateBifObject(
989 _In_ const EVAL_TEST_ENTRY* TestEntry,
990 _In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)
991 {
992 ACPI_EVAL_INPUT_BUFFER InputBuffer;
993 ULONG i, OutputBufferSize;
994 NTSTATUS Status;
995 PACPI_METHOD_ARGUMENT Argument;
996
997 InputBuffer.MethodNameAsUlong = 'FIB_'; // _BIF
998 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
999
1000 OutputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
1001 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) * 9 +
1002 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("1")) +
1003 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("0")) +
1004 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("VBOX")) +
1005 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("innotek"));
1006
1007 /* Evaluate the _BIF method */
1008 Status = DrvCallAcpiDriver(&InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputBufferSize);
1009
1010 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
1011 ok_eq_hex_ex(TestEntry, OutputBuffer->Signature, (ULONG)ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE);
1012 ok_eq_ulong_ex(TestEntry, OutputBuffer->Count, 13LU);
1013 ok_eq_ulong_ex(TestEntry, OutputBuffer->Length, OutputBufferSize);
1014
1015 /* Arguments 1-9 */
1016 Argument = OutputBuffer->Argument;
1017 for (i = 0; i < RTL_NUMBER_OF(DrvpBifIntegerFields); ++i)
1018 {
1019 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_INTEGER);
1020 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof(ULONG));
1021 ok_eq_ulong_ex(TestEntry, Argument->Argument, DrvpBifIntegerFields[i]);
1022
1023 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1024 }
1025 /* Argument 10 */
1026 {
1027 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_STRING);
1028 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof("1")); // Including the trailing null
1029 ok_eq_str_ex(TestEntry, (PCSTR)Argument->Data, "1");
1030 }
1031 /* Argument 11 */
1032 {
1033 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1034
1035 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_STRING);
1036 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof("0"));
1037 ok_eq_str_ex(TestEntry, (PCSTR)Argument->Data, "0");
1038 }
1039 /* Argument 12 */
1040 {
1041 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1042
1043 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_STRING);
1044 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof("VBOX"));
1045 ok_eq_str_ex(TestEntry, (PCSTR)Argument->Data, "VBOX");
1046 }
1047 /* Argument 13 */
1048 {
1049 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1050
1051 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_STRING);
1052 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof("innotek"));
1053 ok_eq_str_ex(TestEntry, (PCSTR)Argument->Data, "innotek");
1054 }
1055 }
1056
1057 static
1058 VOID
DrvTestPackageReturnValueAndStringData(VOID)1059 DrvTestPackageReturnValueAndStringData(VOID)
1060 {
1061 UCHAR Buffer[0x100];
1062 ULONG i;
1063 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)Buffer;
1064
1065 for (i = 0; i < RTL_NUMBER_OF(DrvpBifTests); ++i)
1066 {
1067 RtlZeroMemory(Buffer, sizeof(Buffer));
1068
1069 DrvEvaluateBifObject(&DrvpBifTests[i], OutputBuffer);
1070 }
1071 }
1072
1073 static
1074 VOID
DrvEvaluatePclObject(_In_ const EVAL_TEST_ENTRY * TestEntry,_In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)1075 DrvEvaluatePclObject(
1076 _In_ const EVAL_TEST_ENTRY* TestEntry,
1077 _In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)
1078 {
1079 ACPI_EVAL_INPUT_BUFFER InputBuffer;
1080 ULONG OutputBufferSize;
1081 NTSTATUS Status;
1082 PACPI_METHOD_ARGUMENT Argument;
1083
1084 InputBuffer.MethodNameAsUlong = 'LCP_'; // _PCL
1085 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
1086
1087 OutputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
1088 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("ABCD")); // ACPI name for the object
1089
1090 /* Evaluate the _PCL method */
1091 Status = DrvCallAcpiDriver(&InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputBufferSize);
1092
1093 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
1094 ok_eq_hex_ex(TestEntry, OutputBuffer->Signature, (ULONG)ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE);
1095 ok_eq_ulong_ex(TestEntry, OutputBuffer->Count, 1LU);
1096 ok_eq_ulong_ex(TestEntry, OutputBuffer->Length, OutputBufferSize);
1097
1098 Argument = OutputBuffer->Argument;
1099
1100 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_STRING);
1101 ok_eq_uint_ex(TestEntry, Argument->DataLength, sizeof("ABCD"));
1102 ok_eq_str_ex(TestEntry, (PCSTR)Argument->Data, "_SB_");
1103 }
1104
1105 static
1106 VOID
DrvTestReferenceReturnValue(VOID)1107 DrvTestReferenceReturnValue(VOID)
1108 {
1109 UCHAR Buffer[0x100];
1110 ULONG i;
1111 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)Buffer;
1112
1113 for (i = 0; i < RTL_NUMBER_OF(DrvpPclTests); ++i)
1114 {
1115 RtlZeroMemory(Buffer, sizeof(Buffer));
1116
1117 DrvEvaluatePclObject(&DrvpPclTests[i], OutputBuffer);
1118 }
1119 }
1120
1121 static
1122 VOID
DrvEvaluatePrtObject(_In_ const EVAL_TEST_ENTRY * TestEntry,_In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)1123 DrvEvaluatePrtObject(
1124 _In_ const EVAL_TEST_ENTRY* TestEntry,
1125 _In_ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer)
1126 {
1127 ACPI_EVAL_INPUT_BUFFER InputBuffer;
1128 ULONG PackageNum, ArgNum, OutputBufferSize;
1129 NTSTATUS Status;
1130 PACPI_METHOD_ARGUMENT Argument, PackageArgument;
1131
1132 InputBuffer.MethodNameAsUlong = 'TRP_'; // _PRT
1133 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
1134
1135 #define PRT_PACKAGE_ENTRY_SIZE \
1136 (ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) * 3 + \
1137 ACPI_METHOD_ARGUMENT_LENGTH(sizeof("LNKB")))
1138
1139 OutputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
1140 ACPI_METHOD_ARGUMENT_LENGTH(PRT_PACKAGE_ENTRY_SIZE) * 2;
1141
1142 /* Evaluate the _PRT method */
1143 Status = DrvCallAcpiDriver(&InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputBufferSize);
1144
1145 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
1146 ok_eq_hex_ex(TestEntry, OutputBuffer->Signature, (ULONG)ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE);
1147 ok_eq_ulong_ex(TestEntry, OutputBuffer->Count, 2LU);
1148 ok_eq_ulong_ex(TestEntry, OutputBuffer->Length, OutputBufferSize);
1149
1150 Argument = OutputBuffer->Argument;
1151 for (PackageNum = 0; PackageNum < 2; PackageNum++)
1152 {
1153 ok_eq_uint_ex(TestEntry, Argument->Type, ACPI_METHOD_ARGUMENT_PACKAGE);
1154 ok_eq_uint_ex(TestEntry, Argument->DataLength, (USHORT)PRT_PACKAGE_ENTRY_SIZE);
1155
1156 PackageArgument = (PACPI_METHOD_ARGUMENT)Argument->Data;
1157 for (ArgNum = 0; ArgNum < 4; ArgNum++)
1158 {
1159 if (ArgNum != 2)
1160 {
1161 ULONG ExpectedValue;
1162
1163 ok_eq_uint_ex(TestEntry, PackageArgument->Type, ACPI_METHOD_ARGUMENT_INTEGER);
1164 ok_eq_uint_ex(TestEntry, PackageArgument->DataLength, sizeof(ULONG));
1165
1166 if (ArgNum == 0)
1167 {
1168 ExpectedValue = 0x0002FFFF;
1169 }
1170 else
1171 {
1172 if ((PackageNum == 1) && (ArgNum == 1))
1173 ExpectedValue = 0x00000001;
1174 else
1175 ExpectedValue = 0x00000000;
1176 }
1177 ok_eq_ulong_ex(TestEntry, PackageArgument->Argument, ExpectedValue);
1178 }
1179 else
1180 {
1181 ok_eq_uint_ex(TestEntry, PackageArgument->Type, ACPI_METHOD_ARGUMENT_STRING);
1182 ok_eq_uint_ex(TestEntry, PackageArgument->DataLength, sizeof("ABCD"));
1183 ok_eq_str_ex(TestEntry, (PCSTR)PackageArgument->Data,
1184 (PackageNum == 0) ? "LNKB" : "LNKC");
1185 }
1186
1187 PackageArgument = ACPI_METHOD_NEXT_ARGUMENT(PackageArgument);
1188 }
1189
1190 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1191 }
1192 }
1193
1194 static
1195 VOID
DrvTestNestedPackageReturnValue(VOID)1196 DrvTestNestedPackageReturnValue(VOID)
1197 {
1198 UCHAR Buffer[0x100];
1199 ULONG i;
1200 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)Buffer;
1201
1202 for (i = 0; i < RTL_NUMBER_OF(DrvpPclTests); ++i)
1203 {
1204 RtlZeroMemory(Buffer, sizeof(Buffer));
1205
1206 DrvEvaluatePrtObject(&DrvpPrtTests[i], OutputBuffer);
1207 }
1208 }
1209
1210 static
1211 VOID
DrvEvaluateDsmObject(_In_ const EVAL_TEST_ENTRY * TestEntry)1212 DrvEvaluateDsmObject(
1213 _In_ const EVAL_TEST_ENTRY* TestEntry)
1214 {
1215 #define MY_DSM_SUB_PACKAGE_ENTRY_SIZE \
1216 (ACPI_METHOD_ARGUMENT_LENGTH(sizeof("1_TESTDATATESTDATA_2")))
1217
1218 #define MY_DSM_PACKAGE_ENTRY_SIZE \
1219 (ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) * 3 + \
1220 ACPI_METHOD_ARGUMENT_LENGTH(MY_DSM_SUB_PACKAGE_ENTRY_SIZE))
1221
1222 #define MY_DSM_BUFFER_SIZE \
1223 (FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX, Argument) + \
1224 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(GUID)) + \
1225 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) + \
1226 ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) + \
1227 ACPI_METHOD_ARGUMENT_LENGTH(MY_DSM_PACKAGE_ENTRY_SIZE))
1228
1229 UCHAR Buffer[MY_DSM_BUFFER_SIZE];
1230 ULONG InputSize;
1231 NTSTATUS Status;
1232 PACPI_METHOD_ARGUMENT Argument, PackageArgument, PackageArgument2;
1233 PACPI_EVAL_INPUT_BUFFER_COMPLEX InputBuffer = (PACPI_EVAL_INPUT_BUFFER_COMPLEX)Buffer;
1234
1235 RtlZeroMemory(Buffer, sizeof(Buffer));
1236
1237 InputSize = MY_DSM_BUFFER_SIZE;
1238 if (TestEntry->Flags & DSM_TEST_FLAG_EMPTY_PACKAGE)
1239 {
1240 InputSize -= ACPI_METHOD_ARGUMENT_LENGTH(MY_DSM_PACKAGE_ENTRY_SIZE);
1241 InputSize += ACPI_METHOD_ARGUMENT_LENGTH(ACPI_METHOD_ARGUMENT_LENGTH(0));
1242 }
1243
1244 InputBuffer->MethodNameAsUlong = 'MSD_'; // _DSM
1245 InputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
1246 InputBuffer->ArgumentCount = 4;
1247 InputBuffer->Size = InputSize;
1248
1249 /* Argument 1: The UUID */
1250 Argument = InputBuffer->Argument;
1251 ACPI_METHOD_SET_ARGUMENT_BUFFER(Argument, &MY_DSM_GUID, sizeof(GUID));
1252
1253 /* Argument 2: The Revision ID */
1254 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1255 ACPI_METHOD_SET_ARGUMENT_INTEGER(Argument, 1);
1256
1257 /* Argument 3: The Function Index */
1258 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1259 ACPI_METHOD_SET_ARGUMENT_INTEGER(Argument, 2);
1260
1261 /* Argument 4: The device-specific package */
1262 Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument);
1263 Argument->Type = ACPI_METHOD_ARGUMENT_PACKAGE;
1264 if (TestEntry->Flags & DSM_TEST_FLAG_EMPTY_PACKAGE)
1265 {
1266 /* Empty package */
1267 Argument->DataLength = ACPI_METHOD_ARGUMENT_LENGTH(0);
1268 Argument->Argument = 0;
1269 }
1270 else
1271 {
1272 Argument->DataLength = MY_DSM_PACKAGE_ENTRY_SIZE;
1273
1274 /* Package 1 Argument 1: Some test data */
1275 PackageArgument = (PACPI_METHOD_ARGUMENT)Argument->Data;
1276 ACPI_METHOD_SET_ARGUMENT_INTEGER(PackageArgument, DrvpMyDsmIntegerFields[0]);
1277
1278 /* Package 1 Argument 2: Some test data */
1279 PackageArgument = ACPI_METHOD_NEXT_ARGUMENT(PackageArgument);
1280 ACPI_METHOD_SET_ARGUMENT_INTEGER(PackageArgument, DrvpMyDsmIntegerFields[1]);
1281
1282 /* Package 1 Argument 3: Start a new subpackage */
1283 PackageArgument = ACPI_METHOD_NEXT_ARGUMENT(PackageArgument);
1284 PackageArgument->Type = ACPI_METHOD_ARGUMENT_PACKAGE;
1285 PackageArgument->DataLength = MY_DSM_SUB_PACKAGE_ENTRY_SIZE;
1286
1287 /* Package 2 Argument 1: Some test data */
1288 PackageArgument2 = (PACPI_METHOD_ARGUMENT)PackageArgument->Data;
1289 ACPI_METHOD_SET_ARGUMENT_STRING(PackageArgument2, "1_TESTDATATESTDATA_2");
1290
1291 if (TestEntry->Flags & DSM_TEST_FLAG_LARGE_SUB_PACKAGE_BUFFER)
1292 {
1293 PackageArgument2->DataLength = 32768;
1294 }
1295 else
1296 {
1297 /* Package 1 Argument 4: Some test data */
1298 PackageArgument = ACPI_METHOD_NEXT_ARGUMENT(PackageArgument);
1299 ACPI_METHOD_SET_ARGUMENT_INTEGER(PackageArgument, DrvpMyDsmIntegerFields[2]);
1300 }
1301 }
1302
1303 /* Evaluate the _DSM method */
1304 DrvpEvalTestEntry = TestEntry;
1305 Status = DrvCallAcpiDriver(InputBuffer, InputSize, NULL, 0);
1306
1307 ok_eq_hex_ex(TestEntry, Status, TestEntry->Status);
1308 }
1309
1310 static
1311 VOID
DrvTestPackageInputValue(VOID)1312 DrvTestPackageInputValue(VOID)
1313 {
1314 ULONG i;
1315
1316 for (i = 0; i < RTL_NUMBER_OF(DrvpDsmTests); ++i)
1317 {
1318 DrvEvaluateDsmObject(&DrvpDsmTests[i]);
1319 }
1320 }
1321
1322 static
1323 VOID
DrvTestUnknownMethod(VOID)1324 DrvTestUnknownMethod(VOID)
1325 {
1326 NTSTATUS Status;
1327 ACPI_EVAL_INPUT_BUFFER InputBuffer;
1328
1329 InputBuffer.MethodNameAsUlong = 'FFF_'; // _FFF
1330 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
1331
1332 /* Try to evaluate some unsupported control method */
1333 Status = DrvCallAcpiDriver(&InputBuffer, sizeof(InputBuffer), NULL, 0);
1334
1335 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
1336 }
1337
START_TEST(Bus_PDO_EvalMethod)1338 START_TEST(Bus_PDO_EvalMethod)
1339 {
1340 DrvTestComplexBuffer();
1341 DrvTestInputBuffer();
1342 DrvTestPackageReturnValueAndStringData();
1343 DrvTestReferenceReturnValue();
1344 DrvTestNestedPackageReturnValue();
1345 DrvTestPackageInputValue();
1346 DrvTestUnknownMethod();
1347
1348 ok(DrvpBlocksAllocated == 0, "Leaking memory %ld blocks\n", DrvpBlocksAllocated);
1349 }
1350