2025-04-27 07:49:33 -04:00

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;
}