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 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 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 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 * 228 AcpiOsAllocate ( 229 ACPI_SIZE Size) 230 { 231 return ExAllocatePoolWithTag(NonPagedPool, Size, 'FFUB'); 232 } 233 234 void 235 AcpiOsFree ( 236 void * Memory) 237 { 238 ExFreePoolWithTag(Memory, 'FFUB'); 239 } 240 241 ACPI_STATUS 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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