Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1547 lines
38 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpictl.c
  5. Abstract:
  6. This module handles all of the INTERNAL_DEVICE_CONTROLS requested to
  7. the ACPI driver
  8. Author:
  9. Stephane Plante (splante)
  10. Environment:
  11. NT Kernel Mode Driver only
  12. Revision History:
  13. 01-05-98 - SGP - Complete Rewrite
  14. 01-13-98 - SGP - Cleaned up the Eval Post-Processing
  15. --*/
  16. #include "pch.h"
  17. NTSTATUS
  18. ACPIIoctlAcquireGlobalLock(
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN PIRP Irp,
  21. IN PIO_STACK_LOCATION IrpStack
  22. )
  23. /*++
  24. Routine Description:
  25. This routine acquires the global lock for another device driver
  26. Arguments:
  27. DeviceObject - The device object stack that wants the lock
  28. Irp - The irp with the request in it
  29. Irpstack - The current stack within the irp
  30. Return Value:
  31. NTSTATUS
  32. --*/
  33. {
  34. NTSTATUS status;
  35. PACPI_GLOBAL_LOCK newLock;
  36. PACPI_MANIPULATE_GLOBAL_LOCK_BUFFER outputBuffer;
  37. ULONG outputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  38. //
  39. // Remember that we don't be returning any data
  40. //
  41. Irp->IoStatus.Information = 0;
  42. //
  43. // Is the irp have a minimum size buffer?
  44. //
  45. if (outputLength < sizeof(ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER) ) {
  46. status = STATUS_INFO_LENGTH_MISMATCH;
  47. goto ACPIIoctlAcquireGlobalLockExit;
  48. }
  49. //
  50. // Grab a pointer at the input buffer
  51. //
  52. outputBuffer = (PACPI_MANIPULATE_GLOBAL_LOCK_BUFFER)
  53. Irp->AssociatedIrp.SystemBuffer;
  54. if (outputBuffer->Signature != ACPI_ACQUIRE_GLOBAL_LOCK_SIGNATURE) {
  55. status = STATUS_INVALID_PARAMETER_1;
  56. goto ACPIIoctlAcquireGlobalLockExit;
  57. }
  58. //
  59. // Allocate storage for the lock
  60. //
  61. newLock = ExAllocatePoolWithTag(
  62. NonPagedPool,
  63. sizeof(ACPI_GLOBAL_LOCK),
  64. 'LcpA'
  65. );
  66. if (newLock == NULL) {
  67. status = STATUS_INSUFFICIENT_RESOURCES;
  68. goto ACPIIoctlAcquireGlobalLockExit;
  69. }
  70. RtlZeroMemory( newLock, sizeof(ACPI_GLOBAL_LOCK) );
  71. //
  72. // Initialize the new lock and the request
  73. //
  74. outputBuffer->LockObject = newLock;
  75. Irp->IoStatus.Information = sizeof(ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER);
  76. newLock->LockContext = Irp;
  77. newLock->Type = ACPI_GL_QTYPE_IRP;
  78. //
  79. // Mark the irp as pending, since we can block while acquire the lock
  80. //
  81. IoMarkIrpPending( Irp );
  82. //
  83. // Request the lock now
  84. //
  85. status = ACPIAsyncAcquireGlobalLock( newLock );
  86. if (status == STATUS_PENDING) {
  87. return status;
  88. }
  89. ACPIIoctlAcquireGlobalLockExit:
  90. Irp->IoStatus.Status = status;
  91. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  92. return status;
  93. }
  94. NTSTATUS
  95. ACPIIoctlAsyncEvalControlMethod(
  96. IN PDEVICE_OBJECT DeviceObject,
  97. IN PIRP Irp,
  98. IN PIO_STACK_LOCATION IrpStack
  99. )
  100. /*++
  101. Routine Description:
  102. This routine is called to handle a control method request asynchronously
  103. Arguments:
  104. DeviceObject - The device object to run the method on
  105. Irp - The irp with the request in it
  106. IrpStack - THe current stack within the Irp
  107. Return Value:
  108. NTSTATUS
  109. --*/
  110. {
  111. NTSTATUS status;
  112. PNSOBJ methodObject;
  113. POBJDATA argumentData = NULL;
  114. POBJDATA resultData = NULL;
  115. ULONG argumentCount = 0;
  116. //
  117. // Do the pre processing on the irp
  118. //
  119. status = ACPIIoctlEvalPreProcessing(
  120. DeviceObject,
  121. Irp,
  122. IrpStack,
  123. NonPagedPool,
  124. &methodObject,
  125. &resultData,
  126. &argumentData,
  127. &argumentCount
  128. );
  129. if (!NT_SUCCESS(status)) {
  130. goto ACPIIoctlAsyncEvalControlMethodExit;
  131. }
  132. //
  133. // At this point, we can run the async method
  134. //
  135. status = AMLIAsyncEvalObject(
  136. methodObject,
  137. resultData,
  138. argumentCount,
  139. argumentData,
  140. ACPIIoctlAsyncEvalControlMethodCompletion,
  141. Irp
  142. );
  143. //
  144. // We no longer need the arguments now. Note, that we should clean up
  145. // the argument list because it contains pointer to another block of
  146. // allocated data. Freeing something in the middle of the block would be
  147. // very bad.
  148. //
  149. if (argumentData != NULL) {
  150. ExFreePool( argumentData );
  151. argumentData = NULL;
  152. }
  153. //
  154. // Check the return data now
  155. //
  156. if (status == STATUS_PENDING) {
  157. return status;
  158. } else if (NT_SUCCESS(status)) {
  159. //
  160. // Do the post processing ourselves
  161. //
  162. status = ACPIIoctlEvalPostProcessing(
  163. Irp,
  164. resultData
  165. );
  166. AMLIFreeDataBuffs( resultData, 1 );
  167. }
  168. ACPIIoctlAsyncEvalControlMethodExit:
  169. //
  170. // No longer need this data
  171. //
  172. if (resultData != NULL) {
  173. ExFreePool( resultData );
  174. }
  175. //
  176. // If we got here, then we must complete the irp and return
  177. //
  178. Irp->IoStatus.Status = status;
  179. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  180. return status;
  181. }
  182. VOID EXPORT
  183. ACPIIoctlAsyncEvalControlMethodCompletion(
  184. IN PNSOBJ AcpiObject,
  185. IN NTSTATUS Status,
  186. IN POBJDATA ObjectData,
  187. IN PVOID Context
  188. )
  189. /*++
  190. Routine Description:
  191. This routine is called after the interpreter has had a chance to run
  192. the method
  193. Arguments:
  194. AcpiObject - The object that the method was run on
  195. Status - The status of the eval
  196. ObjectData - The result of the eval
  197. Context - Specific to the caller
  198. Return Value:
  199. NTSTATUS
  200. --*/
  201. {
  202. PIRP irp = (PIRP) Context;
  203. //
  204. // Did we succeed the request?
  205. //
  206. if (NT_SUCCESS(Status)) {
  207. //
  208. // Do the work now
  209. //
  210. Status = ACPIIoctlEvalPostProcessing(
  211. irp,
  212. ObjectData
  213. );
  214. AMLIFreeDataBuffs( ObjectData, 1 );
  215. }
  216. //
  217. // No longer need this data
  218. //
  219. ExFreePool( ObjectData );
  220. //
  221. // If our completion routine got called, then AMLIAsyncEvalObject returned
  222. // STATUS_PENDING. Be sure to mark the IRP pending before we complete it.
  223. //
  224. IoMarkIrpPending(irp);
  225. //
  226. // Complete the request
  227. //
  228. irp->IoStatus.Status = Status;
  229. IoCompleteRequest( irp, IO_NO_INCREMENT );
  230. }
  231. NTSTATUS
  232. ACPIIoctlCalculateOutputBuffer(
  233. IN POBJDATA ObjectData,
  234. IN PACPI_METHOD_ARGUMENT Argument,
  235. IN BOOLEAN TopLevel
  236. )
  237. /*++
  238. Routine Description:
  239. This function is called to fill the contents of Argument with the
  240. information provided by the ObjectData. This function is recursive.
  241. It assumes that the correct amount of storage was allocated for Argument.
  242. Note: To add the ability to return nested packages without breaking W2K
  243. behavior, the outermost package is not part of the output buffer.
  244. I.e. anything that was a package will have its outermost
  245. ACPI_EVAL_OUTPUT_BUFFER.Count be more than 1.
  246. Arguments:
  247. ObjectData - The information that we need to propogate
  248. Argument - The location to propogate that information
  249. TopLevel - Indicates whether we are at the top level of recursion
  250. Return Value:
  251. NTSTATUS
  252. --*/
  253. {
  254. NTSTATUS status;
  255. POBJDATA objData;
  256. PPACKAGEOBJ package;
  257. ULONG count;
  258. ULONG packageCount;
  259. ULONG packageSize;
  260. PACPI_METHOD_ARGUMENT packageArgument;
  261. ASSERT( Argument );
  262. //
  263. // Fill in the output buffer arguments
  264. //
  265. if (ObjectData->dwDataType == OBJTYPE_INTDATA) {
  266. Argument->Type = ACPI_METHOD_ARGUMENT_INTEGER;
  267. Argument->DataLength = sizeof(ULONG);
  268. Argument->Argument = (ULONG) ObjectData->uipDataValue;
  269. } else if (ObjectData->dwDataType == OBJTYPE_STRDATA ||
  270. ObjectData->dwDataType == OBJTYPE_BUFFDATA) {
  271. Argument->Type = (ObjectData->dwDataType == OBJTYPE_STRDATA ?
  272. ACPI_METHOD_ARGUMENT_STRING : ACPI_METHOD_ARGUMENT_BUFFER);
  273. Argument->DataLength = (USHORT)ObjectData->dwDataLen;
  274. RtlCopyMemory(
  275. Argument->Data,
  276. ObjectData->pbDataBuff,
  277. ObjectData->dwDataLen
  278. );
  279. } else if (ObjectData->dwDataType == OBJTYPE_PKGDATA) {
  280. package = (PPACKAGEOBJ) ObjectData->pbDataBuff;
  281. //
  282. // Get the size of the space necessary to store a package's
  283. // data. We are really only interested in the amount of
  284. // data the package will consume *without* its header
  285. // information. Passing TRUE as the last parameter will
  286. // give us that.
  287. //
  288. packageSize = 0;
  289. packageCount = 0;
  290. status = ACPIIoctlCalculateOutputBufferSize(ObjectData,
  291. &packageSize,
  292. &packageCount,
  293. TRUE);
  294. if (!NT_SUCCESS(status)) {
  295. return status;
  296. }
  297. ASSERT(packageCount == package->dwcElements);
  298. if (!TopLevel) {
  299. //
  300. // Create a package argument.
  301. //
  302. Argument->Type = ACPI_METHOD_ARGUMENT_PACKAGE;
  303. Argument->DataLength = (USHORT)packageSize;
  304. packageArgument = (PACPI_METHOD_ARGUMENT)
  305. ((PUCHAR)Argument + FIELD_OFFSET(ACPI_METHOD_ARGUMENT, Data));
  306. } else {
  307. packageArgument = Argument;
  308. }
  309. for (count = 0; count < package->dwcElements; count++) {
  310. objData = &(package->adata[count]);
  311. status = ACPIIoctlCalculateOutputBuffer(
  312. objData,
  313. packageArgument,
  314. FALSE
  315. );
  316. if (!NT_SUCCESS(status)) {
  317. return status;
  318. }
  319. //
  320. // Point to the next argument
  321. //
  322. packageArgument = ACPI_METHOD_NEXT_ARGUMENT(packageArgument);
  323. }
  324. } else {
  325. //
  326. // We don't understand this data type, we won't return anything
  327. //
  328. return STATUS_ACPI_INVALID_DATA;
  329. }
  330. //
  331. // Success
  332. //
  333. return STATUS_SUCCESS;
  334. }
  335. NTSTATUS
  336. ACPIIoctlCalculateOutputBufferSize(
  337. IN POBJDATA ObjectData,
  338. IN PULONG BufferSize,
  339. IN PULONG BufferCount,
  340. IN BOOLEAN TopLevel
  341. )
  342. /*++
  343. Routine Description:
  344. This routine (recursively) calculates the amount of buffer space required
  345. to hold the flattened contents of ObjectData. This information is returned
  346. in BufferSize data location...
  347. If the ObjectData structure contains information that cannot be expressed
  348. to the user, then this routine will return a failure code.
  349. Arguments:
  350. ObjectData - The object whose size we have to calculate
  351. BufferSize - Where to put that size
  352. BufferCount - The number of elements that we are allocating for
  353. Return Value:
  354. NTSTATUS
  355. --*/
  356. {
  357. NTSTATUS status;
  358. POBJDATA objData;
  359. PPACKAGEOBJ package;
  360. ULONG bufferLength;
  361. ULONG count;
  362. ULONG packageCount;
  363. ULONG dummyCount;
  364. //
  365. // Determine how much buffer space is required to hold the
  366. // flattened data structure
  367. //
  368. if (ObjectData->dwDataType == OBJTYPE_INTDATA) {
  369. bufferLength = ACPI_METHOD_ARGUMENT_LENGTH( sizeof(ULONG) );
  370. *BufferCount = 1;
  371. } else if (ObjectData->dwDataType == OBJTYPE_STRDATA ||
  372. ObjectData->dwDataType == OBJTYPE_BUFFDATA) {
  373. bufferLength = ACPI_METHOD_ARGUMENT_LENGTH( ObjectData->dwDataLen );
  374. *BufferCount = 1;
  375. } else if (ObjectData->dwDataType == OBJTYPE_PKGDATA) {
  376. //
  377. // Remember that walking the package means that we have accounted for
  378. // the length of the package and the number of elements within the
  379. // package
  380. //
  381. packageCount = 0;
  382. //
  383. // Walk the package
  384. //
  385. package = (PPACKAGEOBJ) ObjectData->pbDataBuff;
  386. if (!TopLevel) {
  387. //
  388. // Packages are contained in an ACPI_METHOD_ARGUMENT structure.
  389. // So add enough for the overhead of one of these before looking
  390. // at the children.
  391. //
  392. bufferLength = FIELD_OFFSET(ACPI_METHOD_ARGUMENT, Data);
  393. *BufferCount = 1;
  394. } else {
  395. bufferLength = 0;
  396. *BufferCount = package->dwcElements;
  397. }
  398. for (count = 0; count < package->dwcElements; count++) {
  399. objData = &(package->adata[count]);
  400. status = ACPIIoctlCalculateOutputBufferSize(
  401. objData,
  402. BufferSize,
  403. &dummyCount,
  404. FALSE
  405. );
  406. if (!NT_SUCCESS(status)) {
  407. return status;
  408. }
  409. }
  410. } else if (ObjectData->dwDataType == OBJTYPE_UNKNOWN) {
  411. *BufferCount = 1;
  412. bufferLength = 0;
  413. } else {
  414. //
  415. // We don't understand this data type, so we won't return anything
  416. //
  417. ASSERT(FALSE);
  418. return STATUS_ACPI_INVALID_DATA;
  419. }
  420. //
  421. // Update the package lengths
  422. //
  423. ASSERT( BufferSize && BufferCount );
  424. *BufferSize += bufferLength;
  425. return STATUS_SUCCESS;
  426. }
  427. NTSTATUS
  428. ACPIIoctlEvalControlMethod(
  429. IN PDEVICE_OBJECT DeviceObject,
  430. IN PIRP Irp,
  431. IN PIO_STACK_LOCATION IrpStack
  432. )
  433. /*++
  434. Routine Description:
  435. This routine is called to handle a control method request synchronously
  436. Arguments:
  437. DeviceObject - The device object to run the method on
  438. Irp - The irp with the request in it
  439. IrpStack - THe current stack within the Irp
  440. Return Value:
  441. NTSTATUS
  442. --*/
  443. {
  444. NTSTATUS status;
  445. PNSOBJ methodObject;
  446. POBJDATA argumentData = NULL;
  447. POBJDATA resultData = NULL;
  448. ULONG argumentCount = 0;
  449. //
  450. // Do the pre processing on the irp
  451. //
  452. status = ACPIIoctlEvalPreProcessing(
  453. DeviceObject,
  454. Irp,
  455. IrpStack,
  456. PagedPool,
  457. &methodObject,
  458. &resultData,
  459. &argumentData,
  460. &argumentCount
  461. );
  462. if (!NT_SUCCESS(status)) {
  463. goto ACPIIoctlEvalControlMethodExit;
  464. }
  465. //
  466. // At this point, we can run the async method
  467. //
  468. status = AMLIEvalNameSpaceObject(
  469. methodObject,
  470. resultData,
  471. argumentCount,
  472. argumentData
  473. );
  474. //
  475. // We no longer need the arguments now
  476. //
  477. if (argumentData != NULL) {
  478. ExFreePool( argumentData );
  479. argumentData = NULL;
  480. }
  481. //
  482. // Check the return data now and fake a call to the completion routine
  483. //
  484. if (NT_SUCCESS(status)) {
  485. //
  486. // Do the post processing now
  487. //
  488. status = ACPIIoctlEvalPostProcessing(
  489. Irp,
  490. resultData
  491. );
  492. AMLIFreeDataBuffs( resultData, 1 );
  493. }
  494. ACPIIoctlEvalControlMethodExit:
  495. //
  496. // No longer need this data
  497. //
  498. if (resultData != NULL) {
  499. ExFreePool( resultData );
  500. }
  501. //
  502. // If we got here, then we must complete the irp and return
  503. //
  504. Irp->IoStatus.Status = status;
  505. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  506. return status;
  507. }
  508. NTSTATUS
  509. ACPIIoctlEvalPostProcessing(
  510. IN PIRP Irp,
  511. IN POBJDATA ObjectData
  512. )
  513. /*++
  514. Routine Description:
  515. This routine handles convering the ObjectData into information
  516. that can be passed back into the irp.
  517. N.B. This routine does *not* complete the irp. The caller must
  518. do that. This routine is also *not* pageable
  519. Arguments:
  520. Irp - The irp that will hold the results
  521. ObjectData - The result to convert
  522. Return Value:
  523. NTSTATUS - Same as in Irp->IoStatus.Status
  524. --*/
  525. {
  526. NTSTATUS status;
  527. PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  528. PACPI_METHOD_ARGUMENT arg;
  529. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  530. ULONG bufferLength = 0;
  531. ULONG outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  532. ULONG packageCount = 0;
  533. //
  534. // If we don't have an output buffer, then we can complete the request
  535. //
  536. if (outputLength == 0) {
  537. Irp->IoStatus.Information = 0;
  538. return STATUS_SUCCESS;
  539. }
  540. //
  541. // Count the amount of space taken up by the flattened data and how many
  542. // elements of data are contained therein
  543. //
  544. bufferLength = 0;
  545. packageCount = 0;
  546. status = ACPIIoctlCalculateOutputBufferSize(
  547. ObjectData,
  548. &bufferLength,
  549. &packageCount,
  550. TRUE
  551. );
  552. if (!NT_SUCCESS(status)) {
  553. //
  554. // We don't understand a data type in the handling of the data, so
  555. // we won't return anything
  556. //
  557. Irp->IoStatus.Information = 0;
  558. return STATUS_SUCCESS;
  559. }
  560. //
  561. // Add in the fudge factor that we need to account for the Output buffer
  562. //
  563. bufferLength += (sizeof(ACPI_EVAL_OUTPUT_BUFFER) -
  564. sizeof(ACPI_METHOD_ARGUMENT) );
  565. if (bufferLength < sizeof(ACPI_EVAL_OUTPUT_BUFFER)) {
  566. bufferLength = sizeof(ACPI_EVAL_OUTPUT_BUFFER);
  567. }
  568. //
  569. // Setup the Output buffer
  570. //
  571. if (outputLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER)) {
  572. outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER) Irp->AssociatedIrp.SystemBuffer;
  573. outputBuffer->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
  574. outputBuffer->Length = bufferLength;
  575. outputBuffer->Count = packageCount;
  576. arg = outputBuffer->Argument;
  577. }
  578. //
  579. // Make sure that we have enough output buffer space
  580. //
  581. if (bufferLength > outputLength) {
  582. Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER);
  583. return STATUS_BUFFER_OVERFLOW;
  584. } else {
  585. Irp->IoStatus.Information = bufferLength;
  586. }
  587. status = ACPIIoctlCalculateOutputBuffer(
  588. ObjectData,
  589. arg,
  590. TRUE
  591. );
  592. if (!NT_SUCCESS(status)) {
  593. //
  594. // We don't understand a data type in the handling of the data, so we
  595. // won't return anything
  596. //
  597. Irp->IoStatus.Information = 0;
  598. return STATUS_SUCCESS;
  599. }
  600. //
  601. // Done
  602. //
  603. return STATUS_SUCCESS;
  604. }
  605. NTSTATUS
  606. ACPIIoctlEvalPreProcessing(
  607. IN PDEVICE_OBJECT DeviceObject,
  608. IN PIRP Irp,
  609. IN PIO_STACK_LOCATION IrpStack,
  610. IN POOL_TYPE PoolType,
  611. OUT PNSOBJ *MethodObject,
  612. OUT POBJDATA *ResultData,
  613. OUT POBJDATA *ArgumentData,
  614. OUT ULONG *ArgumentCount
  615. )
  616. /*++
  617. Routine Description:
  618. This routine converts the request in an Irp into the structures
  619. required by the AML Interpreter
  620. N.B. This routine does *not* complete the irp. The caller must
  621. do that. This routine is also *not* pageable
  622. Arguments:
  623. Irp - The request
  624. IrpStack - The current stack location in the request
  625. PoolType - Which type of memory to allocate
  626. MethodObject - Pointer to which object to run
  627. ResultData - Pointer to where to store the result
  628. ArgumentData - Pointer to the arguments
  629. ArgumentCount - Potiner to the number of arguments
  630. Return Value:
  631. NTSTATUS
  632. --*/
  633. {
  634. NTSTATUS status;
  635. PACPI_EVAL_INPUT_BUFFER inputBuffer;
  636. PNSOBJ acpiObject;
  637. PNSOBJ methodObject;
  638. POBJDATA argumentData = NULL;
  639. POBJDATA resultData = NULL;
  640. UCHAR methodName[5];
  641. ULONG argumentCount = 0;
  642. ULONG inputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  643. ULONG outputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  644. //
  645. // Do this step before we do anything else --- this way we won't
  646. // overwrite anything is someone tries to return some data
  647. //
  648. Irp->IoStatus.Information = 0;
  649. //
  650. // Is the irp have a minimum size buffer?
  651. //
  652. if (inputLength < sizeof(ACPI_EVAL_INPUT_BUFFER) ) {
  653. return STATUS_INFO_LENGTH_MISMATCH;
  654. }
  655. //
  656. // Do we have a non-null output length? if so, then it must meet the
  657. // minimum size
  658. //
  659. if (outputLength != 0 && outputLength < sizeof(ACPI_EVAL_OUTPUT_BUFFER)) {
  660. return STATUS_BUFFER_TOO_SMALL;
  661. }
  662. //
  663. // Grab a pointer at the input buffer
  664. //
  665. inputBuffer = (PACPI_EVAL_INPUT_BUFFER) Irp->AssociatedIrp.SystemBuffer;
  666. //
  667. // Convert the name to a null terminated string
  668. //
  669. RtlZeroMemory( methodName, 5 * sizeof(UCHAR) );
  670. RtlCopyMemory( methodName, inputBuffer->MethodName, sizeof(NAMESEG) );
  671. //
  672. // Search for the name space object that corresponds to the one that we
  673. // being asked about
  674. //
  675. acpiObject = OSConvertDeviceHandleToPNSOBJ( DeviceObject );
  676. if (acpiObject == NULL) {
  677. return STATUS_NO_SUCH_DEVICE;
  678. }
  679. status = AMLIGetNameSpaceObject(
  680. methodName,
  681. acpiObject,
  682. &methodObject,
  683. NSF_LOCAL_SCOPE
  684. );
  685. if (!NT_SUCCESS(status)) {
  686. return status;
  687. }
  688. //
  689. // Allocate memory for return data
  690. //
  691. resultData = ExAllocatePoolWithTag( PoolType, sizeof(OBJDATA), 'RcpA' );
  692. if (resultData == NULL) {
  693. return STATUS_INSUFFICIENT_RESOURCES;
  694. }
  695. //
  696. // What we do is really based on what the signature in this buffer is
  697. //
  698. switch (inputBuffer->Signature) {
  699. case ACPI_EVAL_INPUT_BUFFER_SIGNATURE:
  700. //
  701. // Nothing to do here
  702. //
  703. break;
  704. case ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE:
  705. case ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE:
  706. //
  707. // We need to create a single argument to pass to the function
  708. //
  709. argumentCount = 1;
  710. argumentData = ExAllocatePoolWithTag(
  711. PoolType,
  712. sizeof(OBJDATA),
  713. 'AcpA'
  714. );
  715. if (argumentData == NULL) {
  716. ExFreePool( resultData );
  717. return STATUS_INSUFFICIENT_RESOURCES;
  718. }
  719. //
  720. // Initialize the argument to the proper value
  721. //
  722. RtlZeroMemory( argumentData, sizeof(OBJDATA) );
  723. if (inputBuffer->Signature == ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE) {
  724. PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER integerBuffer;
  725. integerBuffer = (PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER) inputBuffer;
  726. argumentData->dwDataType = OBJTYPE_INTDATA;
  727. argumentData->uipDataValue = integerBuffer->IntegerArgument;
  728. } else {
  729. PACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING stringBuffer;
  730. stringBuffer = (PACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING) inputBuffer;
  731. argumentData->dwDataType = OBJTYPE_STRDATA;
  732. argumentData->dwDataLen = stringBuffer->StringLength;
  733. argumentData->pbDataBuff = stringBuffer->String;
  734. }
  735. break;
  736. case ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE: {
  737. PACPI_EVAL_INPUT_BUFFER_COMPLEX complexBuffer;
  738. PACPI_METHOD_ARGUMENT methodArgument;
  739. ULONG i;
  740. complexBuffer = (PACPI_EVAL_INPUT_BUFFER_COMPLEX) inputBuffer;
  741. //
  742. // Do we need to create any arguments?
  743. //
  744. if (complexBuffer->ArgumentCount == 0) {
  745. break;
  746. }
  747. //
  748. // Create the object data structures to hold these arguments
  749. //
  750. argumentCount = complexBuffer->ArgumentCount;
  751. methodArgument = complexBuffer->Argument;
  752. argumentData = ExAllocatePoolWithTag(
  753. PoolType,
  754. sizeof(OBJDATA) * argumentCount,
  755. 'AcpA'
  756. );
  757. if (argumentData == NULL) {
  758. ExFreePool( resultData );
  759. return STATUS_INSUFFICIENT_RESOURCES;
  760. }
  761. RtlZeroMemory( argumentData, argumentCount * sizeof(OBJDATA) );
  762. for (i = 0; i < argumentCount; i++) {
  763. if (methodArgument->Type == ACPI_METHOD_ARGUMENT_INTEGER) {
  764. (argumentData[i]).dwDataType = OBJTYPE_INTDATA;
  765. (argumentData[i]).uipDataValue = methodArgument->Argument;
  766. } else {
  767. (argumentData[i]).dwDataLen = methodArgument->DataLength;
  768. (argumentData[i]).pbDataBuff = methodArgument->Data;
  769. if (methodArgument->Type == ACPI_METHOD_ARGUMENT_STRING) {
  770. (argumentData[i]).dwDataType = OBJTYPE_STRDATA;
  771. } else {
  772. (argumentData[i]).dwDataType = OBJTYPE_BUFFDATA;
  773. }
  774. }
  775. //
  776. // Look at the next method
  777. //
  778. methodArgument = ACPI_METHOD_NEXT_ARGUMENT( methodArgument );
  779. }
  780. break;
  781. }
  782. default:
  783. return STATUS_INVALID_PARAMETER_1;
  784. }
  785. //
  786. // Set the proper pointers
  787. //
  788. *MethodObject = methodObject;
  789. *ResultData = resultData;
  790. *ArgumentData = argumentData;
  791. *ArgumentCount = argumentCount;
  792. //
  793. // Done pre-processing
  794. //
  795. return STATUS_SUCCESS;
  796. }
  797. NTSTATUS
  798. ACPIIoctlRegisterOpRegionHandler(
  799. IN PDEVICE_OBJECT DeviceObject,
  800. IN PIRP Irp,
  801. IN PIO_STACK_LOCATION IrpStack
  802. )
  803. /*++
  804. Routine Description:
  805. This routine handle the registration of the an Operation Region
  806. Arguments:
  807. DeviceObject - The DeviceObject that the region is getting
  808. registered on
  809. Irp - The request
  810. IrpStack - Our part of the request
  811. Return Value
  812. Status
  813. --*/
  814. {
  815. NTSTATUS status;
  816. PACPI_REGISTER_OPREGION_HANDLER_BUFFER inputBuffer;
  817. PACPI_UNREGISTER_OPREGION_HANDLER_BUFFER outputBuffer;
  818. PNSOBJ regionObject;
  819. PVOID opregionObject;
  820. ULONG accessType;
  821. ULONG inputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  822. ULONG outputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  823. ULONG regionSpace;
  824. //
  825. // Grab the acpi object that corresponds to the current one
  826. //
  827. regionObject = OSConvertDeviceHandleToPNSOBJ( DeviceObject );
  828. //
  829. // Preload this value. This is so that we don't have to remember how
  830. // many bytes we will return
  831. //
  832. Irp->IoStatus.Information = sizeof(ACPI_REGISTER_OPREGION_HANDLER_BUFFER);
  833. //
  834. // Is the irp have a minimum size buffer?
  835. //
  836. if (inputLength < sizeof(ACPI_REGISTER_OPREGION_HANDLER_BUFFER) ) {
  837. status = STATUS_INFO_LENGTH_MISMATCH;
  838. goto ACPIIoctlRegisterOpRegionHandlerExit;
  839. }
  840. //
  841. // Do we have a non-null output length? if so, then it must meet the
  842. // minimum size
  843. //
  844. if (outputLength < sizeof(ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER) ) {
  845. status = STATUS_BUFFER_TOO_SMALL;
  846. goto ACPIIoctlRegisterOpRegionHandlerExit;
  847. }
  848. //
  849. // Grab a pointer at the input buffer
  850. //
  851. inputBuffer = (PACPI_REGISTER_OPREGION_HANDLER_BUFFER)
  852. Irp->AssociatedIrp.SystemBuffer;
  853. //
  854. // Is this an input buffer?
  855. //
  856. if (inputBuffer->Signature != ACPI_REGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE) {
  857. status = STATUS_ACPI_INVALID_DATA;
  858. goto ACPIIoctlRegisterOpRegionHandlerExit;
  859. }
  860. //
  861. // Set the correct access type
  862. //
  863. switch (inputBuffer->AccessType) {
  864. case ACPI_OPREGION_ACCESS_AS_RAW:
  865. accessType = EVTYPE_RS_RAWACCESS;
  866. break;
  867. case ACPI_OPREGION_ACCESS_AS_COOKED:
  868. accessType = EVTYPE_RS_COOKACCESS;
  869. break;
  870. default:
  871. status = STATUS_ACPI_INVALID_DATA;
  872. goto ACPIIoctlRegisterOpRegionHandlerExit;
  873. }
  874. //
  875. // Set the correct region space
  876. //
  877. switch (inputBuffer->RegionSpace) {
  878. case ACPI_OPREGION_REGION_SPACE_MEMORY:
  879. regionSpace = REGSPACE_MEM;
  880. break;
  881. case ACPI_OPREGION_REGION_SPACE_IO:
  882. regionSpace = REGSPACE_IO;
  883. break;
  884. case ACPI_OPREGION_REGION_SPACE_PCI_CONFIG:
  885. regionSpace = REGSPACE_PCICFG;
  886. break;
  887. case ACPI_OPREGION_REGION_SPACE_EC:
  888. regionSpace = REGSPACE_EC;
  889. break;
  890. case ACPI_OPREGION_REGION_SPACE_SMB:
  891. regionSpace = REGSPACE_SMB;
  892. break;
  893. case ACPI_OPREGION_REGION_SPACE_CMOS_CONFIG:
  894. regionSpace = REGSPACE_CMOSCFG;
  895. break;
  896. case ACPI_OPREGION_REGION_SPACE_PCIBARTARGET:
  897. regionSpace = REGSPACE_PCIBARTARGET;
  898. break;
  899. default:
  900. if (inputBuffer->RegionSpace >= 0x80 &&
  901. inputBuffer->RegionSpace <= 0xff ) {
  902. //
  903. // This one is vendor-defined. Just use
  904. // the value that the vendor passed in.
  905. //
  906. regionSpace = inputBuffer->RegionSpace;
  907. break;
  908. }
  909. status = STATUS_ACPI_INVALID_DATA;
  910. goto ACPIIoctlRegisterOpRegionHandlerExit;
  911. }
  912. //
  913. // Evaluate the registration
  914. //
  915. status = RegisterOperationRegionHandler(
  916. regionObject,
  917. accessType,
  918. regionSpace,
  919. (PFNHND) inputBuffer->Handler,
  920. (ULONG_PTR)inputBuffer->Context,
  921. &opregionObject
  922. );
  923. //
  924. // If we succeeded, then setup the output buffer
  925. //
  926. if (NT_SUCCESS(status)) {
  927. outputBuffer = (PACPI_UNREGISTER_OPREGION_HANDLER_BUFFER)
  928. Irp->AssociatedIrp.SystemBuffer;
  929. outputBuffer->Signature = ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE;
  930. outputBuffer->OperationRegionObject = opregionObject;
  931. Irp->IoStatus.Information =
  932. sizeof(ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER);
  933. }
  934. ACPIIoctlRegisterOpRegionHandlerExit:
  935. //
  936. // Done with the request
  937. //
  938. Irp->IoStatus.Status = status;
  939. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  940. //
  941. // return with the status code
  942. //
  943. return status;
  944. }
  945. NTSTATUS
  946. ACPIIoctlReleaseGlobalLock(
  947. IN PDEVICE_OBJECT DeviceObject,
  948. IN PIRP Irp,
  949. IN PIO_STACK_LOCATION IrpStack
  950. )
  951. /*++
  952. Routine Description:
  953. This routine is called to release the global lock
  954. Arguments:
  955. DeviceObject - The Device object that is releasing the lock
  956. Irp - The request
  957. IrpStack - Our part of the request
  958. Return Value:
  959. NTSTATUS
  960. --*/
  961. {
  962. NTSTATUS status;
  963. PACPI_GLOBAL_LOCK acpiLock;
  964. PACPI_MANIPULATE_GLOBAL_LOCK_BUFFER inputBuffer;
  965. ULONG inputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  966. //
  967. // Remember that we don't be returning any data
  968. //
  969. Irp->IoStatus.Information = 0;
  970. //
  971. // Is the irp have a minimum size buffer?
  972. //
  973. if (inputLength < sizeof(ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER) ) {
  974. status = STATUS_INFO_LENGTH_MISMATCH;
  975. goto ACPIIoctlReleaseGlobalLockExit;
  976. }
  977. //
  978. // Grab a pointer at the input buffer
  979. //
  980. inputBuffer = (PACPI_MANIPULATE_GLOBAL_LOCK_BUFFER)
  981. Irp->AssociatedIrp.SystemBuffer;
  982. if (inputBuffer->Signature != ACPI_RELEASE_GLOBAL_LOCK_SIGNATURE) {
  983. status = STATUS_INVALID_PARAMETER_1;
  984. goto ACPIIoctlReleaseGlobalLockExit;
  985. }
  986. acpiLock = inputBuffer->LockObject;
  987. //
  988. // Release the lock now
  989. //
  990. status = ACPIReleaseGlobalLock( acpiLock );
  991. //
  992. // Free the memory for the lock
  993. //
  994. ExFreePool( acpiLock );
  995. ACPIIoctlReleaseGlobalLockExit:
  996. Irp->IoStatus.Status = status;
  997. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  998. //
  999. // Done
  1000. //
  1001. return status;
  1002. }
  1003. NTSTATUS
  1004. ACPIIoctlUnRegisterOpRegionHandler(
  1005. IN PDEVICE_OBJECT DeviceObject,
  1006. IN PIRP Irp,
  1007. IN PIO_STACK_LOCATION IrpStack
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. This routine handle the unregistration of the an Operation Region
  1012. Arguments:
  1013. DeviceObject - The DeviceObject that the region is getting
  1014. registered on
  1015. Irp - The request
  1016. IrpStack - Our part of the request
  1017. NTSTATUS
  1018. Status
  1019. --*/
  1020. {
  1021. NTSTATUS status;
  1022. PACPI_UNREGISTER_OPREGION_HANDLER_BUFFER inputBuffer;
  1023. PNSOBJ regionObject;
  1024. ULONG inputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  1025. //
  1026. // Grab the region object that corresponds to the requested on
  1027. //
  1028. regionObject = OSConvertDeviceHandleToPNSOBJ( DeviceObject );
  1029. //
  1030. // Is the irp have a minimum size buffer?
  1031. //
  1032. if (inputLength < sizeof(ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER) ) {
  1033. status = STATUS_INFO_LENGTH_MISMATCH;
  1034. goto ACPIIoctlUnRegisterOpRegionHandlerExit;
  1035. }
  1036. //
  1037. // Grab a pointer at the input buffer
  1038. //
  1039. inputBuffer = (PACPI_UNREGISTER_OPREGION_HANDLER_BUFFER)
  1040. Irp->AssociatedIrp.SystemBuffer;
  1041. //
  1042. // Evaluate the registration
  1043. //
  1044. status = UnRegisterOperationRegionHandler(
  1045. regionObject,
  1046. inputBuffer->OperationRegionObject
  1047. );
  1048. ACPIIoctlUnRegisterOpRegionHandlerExit:
  1049. //
  1050. // Done with the request
  1051. //
  1052. Irp->IoStatus.Status = status;
  1053. Irp->IoStatus.Information = 0;
  1054. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1055. //
  1056. // return with the status code
  1057. //
  1058. return status;
  1059. }
  1060. NTSTATUS
  1061. ACPIIrpDispatchDeviceControl(
  1062. IN PDEVICE_OBJECT DeviceObject,
  1063. IN PIRP Irp
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This routine handles the INTERNAL_DEVICE_CONTROLs that are sent to
  1068. an ACPI Device Object
  1069. Arguments:
  1070. DeviceObject - The device object that received the request
  1071. Irp - The request
  1072. Return Value:
  1073. NTSTATUS
  1074. --*/
  1075. {
  1076. NTSTATUS status;
  1077. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1078. ULONG ioctlCode;
  1079. //
  1080. // Make sure that this is an internally generated irp
  1081. //
  1082. if (Irp->RequestorMode != KernelMode) {
  1083. status = ACPIDispatchForwardIrp( DeviceObject, Irp );
  1084. return status;
  1085. }
  1086. //
  1087. // Grab what we need out of the current irp stack
  1088. //
  1089. ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  1090. //
  1091. // What is the IOCTL that we need to handle?
  1092. //
  1093. switch (ioctlCode ) {
  1094. case IOCTL_ACPI_ASYNC_EVAL_METHOD:
  1095. //
  1096. // Handle this elsewhere
  1097. //
  1098. status = ACPIIoctlAsyncEvalControlMethod(
  1099. DeviceObject,
  1100. Irp,
  1101. irpStack
  1102. );
  1103. break;
  1104. case IOCTL_ACPI_EVAL_METHOD:
  1105. //
  1106. // Handle this elsewhere
  1107. //
  1108. status = ACPIIoctlEvalControlMethod(
  1109. DeviceObject,
  1110. Irp,
  1111. irpStack
  1112. );
  1113. break;
  1114. case IOCTL_ACPI_REGISTER_OPREGION_HANDLER:
  1115. //
  1116. // Handle this elsewhere
  1117. //
  1118. status = ACPIIoctlRegisterOpRegionHandler(
  1119. DeviceObject,
  1120. Irp,
  1121. irpStack
  1122. );
  1123. break;
  1124. case IOCTL_ACPI_UNREGISTER_OPREGION_HANDLER:
  1125. //
  1126. // Handle this elsewhere
  1127. //
  1128. status = ACPIIoctlUnRegisterOpRegionHandler(
  1129. DeviceObject,
  1130. Irp,
  1131. irpStack
  1132. );
  1133. break;
  1134. case IOCTL_ACPI_ACQUIRE_GLOBAL_LOCK:
  1135. //
  1136. // Handle this elsewhere
  1137. //
  1138. status = ACPIIoctlAcquireGlobalLock(
  1139. DeviceObject,
  1140. Irp,
  1141. irpStack
  1142. );
  1143. break;
  1144. case IOCTL_ACPI_RELEASE_GLOBAL_LOCK:
  1145. //
  1146. // Handle this elsewhere
  1147. //
  1148. status = ACPIIoctlReleaseGlobalLock(
  1149. DeviceObject,
  1150. Irp,
  1151. irpStack
  1152. );
  1153. break;
  1154. default:
  1155. //
  1156. // Handle this with the default mechanism
  1157. //
  1158. status = ACPIDispatchForwardIrp( DeviceObject, Irp );
  1159. }
  1160. //
  1161. // Done
  1162. //
  1163. return status;
  1164. }