363 lines
8.6 KiB
C
363 lines
8.6 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
util.c
|
|
|
|
Abstract:
|
|
|
|
ACPI BIOS Simulator / Generic 3rd Party Operation Region Provider
|
|
Utility module
|
|
|
|
Author(s):
|
|
|
|
Vincent Geglia
|
|
Michael T. Murphy
|
|
Chris Burgess
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
//
|
|
// General includes
|
|
//
|
|
|
|
#include "ntddk.h"
|
|
#include "acpiioct.h"
|
|
|
|
//
|
|
// Specific includes
|
|
//
|
|
|
|
#include "asimlib.h"
|
|
#include "util.h"
|
|
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
NTSTATUS
|
|
AcpisimEvalAcpiMethod
|
|
(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PUCHAR MethodName,
|
|
OPTIONAL PVOID *Result
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine evaluates an ACPI method, and returns the result
|
|
if the caller passes in a pointer to a PVOID.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object
|
|
MethodName - a 4 character method name of the method to evaluate
|
|
Result - a pointer to a PVOID will contain a result (NOTE: Caller
|
|
MUST call ExFreePool on the pointer when finished)
|
|
|
|
Return Value:
|
|
|
|
Status code of operation
|
|
|
|
--*/
|
|
|
|
{
|
|
ACPI_EVAL_INPUT_BUFFER inputbuffer;
|
|
ACPI_EVAL_OUTPUT_BUFFER outputbuffer;
|
|
KEVENT event;
|
|
IO_STATUS_BLOCK iostatus;
|
|
NTSTATUS status;
|
|
PIRP irp;
|
|
|
|
DBG_PRINT (DBG_INFO, "Entering AcpisimEvalAcpiMethod\n");
|
|
|
|
//
|
|
// Initialize the event
|
|
//
|
|
|
|
KeInitializeEvent (&event, SynchronizationEvent, FALSE );
|
|
|
|
//
|
|
// Initialize the input buffer
|
|
//
|
|
|
|
DBG_PRINT (DBG_INFO,
|
|
"Evaluating method '%c%c%c%c'\n",
|
|
MethodName[0],
|
|
MethodName[1],
|
|
MethodName[2],
|
|
MethodName[3]);
|
|
|
|
|
|
RtlZeroMemory (&inputbuffer, sizeof (ACPI_EVAL_INPUT_BUFFER));
|
|
inputbuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|
RtlCopyMemory (&inputbuffer.MethodName, MethodName, 4);
|
|
|
|
//
|
|
// Initialize the output buffer
|
|
//
|
|
|
|
RtlZeroMemory (&outputbuffer, sizeof (ACPI_EVAL_OUTPUT_BUFFER));
|
|
|
|
//
|
|
// Initialize an IRP
|
|
//
|
|
|
|
irp = IoBuildDeviceIoControlRequest (IOCTL_ACPI_EVAL_METHOD,
|
|
AcpisimLibGetNextDevice (DeviceObject),
|
|
&inputbuffer,
|
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|
&outputbuffer,
|
|
sizeof(ACPI_EVAL_OUTPUT_BUFFER),
|
|
FALSE,
|
|
&event,
|
|
&iostatus);
|
|
|
|
//
|
|
// Irp initialization failed?
|
|
//
|
|
|
|
if (!irp) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "AcpisimEvalAcpiMethod: Failed to create IRP\n");
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto ExitAcpisimEvalAcpiMethod;
|
|
}
|
|
|
|
//
|
|
// Send to ACPI driver
|
|
//
|
|
|
|
status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
//
|
|
// Wait for request to be completed
|
|
//
|
|
|
|
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
//
|
|
// Get the real status
|
|
//
|
|
|
|
status = iostatus.Status;
|
|
}
|
|
|
|
//
|
|
// Did we fail the request?
|
|
//
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "AcpisimEvalAcpiMethod: Lower driver failed IRP (%lx)\n", status);
|
|
|
|
goto ExitAcpisimEvalAcpiMethod;
|
|
}
|
|
|
|
//
|
|
// Make sure the result is correct
|
|
//
|
|
|
|
ASSERT (iostatus.Information >= sizeof(ACPI_EVAL_OUTPUT_BUFFER));
|
|
|
|
if (iostatus.Information < sizeof(ACPI_EVAL_OUTPUT_BUFFER) ||
|
|
outputbuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
|
|
outputbuffer.Count == 0) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ExitAcpisimEvalAcpiMethod;
|
|
|
|
}
|
|
|
|
if (Result) {
|
|
|
|
*Result = ExAllocatePoolWithTag (
|
|
NonPagedPool,
|
|
iostatus.Information,
|
|
ACPISIM_TAG
|
|
);
|
|
|
|
if (!*Result) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "Unable to allocate memory for result.\n");
|
|
goto ExitAcpisimEvalAcpiMethod;
|
|
}
|
|
|
|
RtlCopyMemory (*Result, &outputbuffer, iostatus.Information);
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
ExitAcpisimEvalAcpiMethod:
|
|
|
|
DBG_PRINT (DBG_INFO, "Exiting AcpisimEvalAcpiMethod\n");
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
AcpisimEvalAcpiMethodComplex
|
|
(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PVOID InputBuffer,
|
|
OPTIONAL PVOID *Result
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine evaluates an ACPI method, but allows the
|
|
passing in of parameters.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object
|
|
MethodName - a 4 character method name of the method to evaluate
|
|
Result - a pointer to a PVOID will contain a result (NOTE: Caller
|
|
MUST call ExFreePool on the pointer when finished)
|
|
|
|
Return Value:
|
|
|
|
Status code of operation
|
|
|
|
--*/
|
|
|
|
{
|
|
ACPI_EVAL_OUTPUT_BUFFER outputbuffer;
|
|
KEVENT event;
|
|
IO_STATUS_BLOCK iostatus;
|
|
NTSTATUS status;
|
|
PIRP irp;
|
|
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputbuffer = (PACPI_EVAL_INPUT_BUFFER_COMPLEX) InputBuffer;
|
|
|
|
DBG_PRINT (DBG_INFO, "Entering AcpisimEvalAcpiMethodComplex\n");
|
|
|
|
//
|
|
// Initialize the event
|
|
//
|
|
|
|
KeInitializeEvent (&event, SynchronizationEvent, FALSE );
|
|
|
|
|
|
//
|
|
// Initialize the output buffer
|
|
//
|
|
|
|
RtlZeroMemory (&outputbuffer, sizeof (ACPI_EVAL_OUTPUT_BUFFER));
|
|
|
|
//
|
|
// Initialize an IRP
|
|
//
|
|
|
|
irp = IoBuildDeviceIoControlRequest (IOCTL_ACPI_EVAL_METHOD,
|
|
AcpisimLibGetNextDevice (DeviceObject),
|
|
inputbuffer,
|
|
inputbuffer->Size,
|
|
&outputbuffer,
|
|
sizeof(ACPI_EVAL_OUTPUT_BUFFER),
|
|
FALSE,
|
|
&event,
|
|
&iostatus);
|
|
|
|
//
|
|
// Irp initialization failed?
|
|
//
|
|
|
|
if (!irp) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "AcpisimEvalAcpiMethodComplex: Failed to create IRP\n");
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto ExitAcpisimEvalAcpiMethodComplex;
|
|
}
|
|
|
|
//
|
|
// Send to ACPI driver
|
|
//
|
|
|
|
status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
//
|
|
// Wait for request to be completed
|
|
//
|
|
|
|
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
//
|
|
// Get the real status
|
|
//
|
|
|
|
status = iostatus.Status;
|
|
}
|
|
|
|
//
|
|
// Did we fail the request?
|
|
//
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "AcpisimEvalAcpiMethodComplex: Lower driver failed IRP (%lx)\n", status);
|
|
|
|
goto ExitAcpisimEvalAcpiMethodComplex;
|
|
}
|
|
|
|
//
|
|
// Make sure the result is correct
|
|
//
|
|
|
|
ASSERT (iostatus.Information >= sizeof(ACPI_EVAL_OUTPUT_BUFFER));
|
|
|
|
if (iostatus.Information < sizeof(ACPI_EVAL_OUTPUT_BUFFER) ||
|
|
outputbuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
|
|
outputbuffer.Count == 0) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ExitAcpisimEvalAcpiMethodComplex;
|
|
|
|
}
|
|
|
|
if (Result) {
|
|
|
|
*Result = ExAllocatePoolWithTag (
|
|
NonPagedPool,
|
|
iostatus.Information,
|
|
ACPISIM_TAG
|
|
);
|
|
|
|
if (!*Result) {
|
|
|
|
DBG_PRINT (DBG_ERROR, "Unable to allocate memory for result.\n");
|
|
goto ExitAcpisimEvalAcpiMethodComplex;
|
|
}
|
|
|
|
RtlCopyMemory (*Result, &outputbuffer, iostatus.Information);
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
ExitAcpisimEvalAcpiMethodComplex:
|
|
|
|
DBG_PRINT (DBG_INFO, "Exiting AcpisimEvalAcpiMethodComplex\n");
|
|
|
|
return status;
|
|
}
|