Driver for ACPI device ASL evaluation

xxxxx@yahoo.com wrote:

For the legal concern, please forgive me I can’t post the complete ASL, but below are the key piese for my questions (I think, pls correct me if you need more details…):

Scope(_SB){
Device(AKDV){
Name(_HID,“ADV0001”)
Method(_INI){
… skip …
}
Method(RTN0,0){
Return(0)
}
… skip …
}

Hope it’s helpful. and thank you for your continual help.

Yep, that would seem to answer my concerns…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I recently wrote a device driver that did essentially what the OP is trying
to do. If you’ve verified that you code in your driver is being executed
when your application invokes it (and it appears that you have) then you’ve
probably not satisfied the ACPI driver’s notion of what the method
invocation should look like.

The code in my driver that invokes an ACPI method looks like this. Note
that the method is specified to return a package of two elements, each of
which are integers, which is why the code is expecting that:

#define OUTPUT_BUF_SIZE (sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
(sizeof(ACPI_METHOD_ARGUMENT) * 2))

ACPI_EVAL_INPUT_BUFFER inputBuf;
PACPI_METHOD_ARGUMENT acpiObj;
Pxxx_EXTENSION devExt = GetContext(Device);
WDF_MEMORY_DESCRIPTOR inputDesc;
WDF_MEMORY_DESCRIPTOR outputDesc;
ULONG_PTR bytesReturned;
NTSTATUS status;
UCHAR outputBuf[OUTPUT_BUF_SIZE];

PAGED_CODE();

//
// Send an IOCTL down to ACPI.sys asking to evaluate the package that
// contains the physical address of the generation counter.
//

inputBuf.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
inputBuf.MethodNameAsUlong = ‘0ZYX’; // XYZ0 expressed little-endian
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDesc, &inputBuf,
sizeof(inputBuf));

RtlZeroMemory(&outputBuf, OUTPUT_BUF_SIZE);
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDesc, &outputBuf,
OUTPUT_BUF_SIZE);

status = WdfIoTargetSendIoctlSynchronously(WdfDeviceGetIoTarget(Device),
WDF_NO_HANDLE,
IOCTL_ACPI_EVAL_METHOD,
&inputDesc,
&outputDesc,
NULL,
&bytesReturned);

if (!NT_SUCCESS(status))
{
return status;
}

NT_ASSERT(bytesReturned != 0);

if (((PACPI_EVAL_OUTPUT_BUFFER)outputBuf)->Signature !=
ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE)
{
return STATUS_NOT_FOUND;
}

//
// If the ACPI driver didn’t return three arguments, then the BIOS
doesn’t
// really match the spec.
//

if (((PACPI_EVAL_OUTPUT_BUFFER)outputBuf)->Count != 2)
{
return STATUS_INVALID_PARAMETER;
}

acpiObj = ((PACPI_EVAL_OUTPUT_BUFFER)outputBuf)->Argument;

if (acpiObj->Type != ACPI_METHOD_ARGUMENT_INTEGER)
{
return STATUS_INVALID_PARAMETER;
}

Jake Oshins
Hyper-V I/O Architect (and former ACPI guy)
Windows Kernel Group

This post implies no warranties and confers no rights.


“Tim Roberts” wrote in message news:xxxxx@ntdev…

xxxxx@yahoo.com wrote:

For the legal concern, please forgive me I can’t post the complete
ASL, but below are the key piese for my questions (I think, pls correct me
if you need more details…):

Scope(_SB){
Device(AKDV){
Name(_HID,“ADV0001”)
Method(_INI){
… skip …
}
Method(RTN0,0){
Return(0)
}
… skip …
}

Hope it’s helpful. and thank you for your continual help.

Yep, that would seem to answer my concerns…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi! Peter,

Sorry for my late reply (w/o internet access yesterday).

It’s AccessADRV99_ASL_RTNO_Method

-tftu

Hi! Jake,

Thank you for your advise. I’m out of office since Wed. and will not return until Mon. Will try to adopt your code and let you know the result then.

Best Regards,

-tftu

Hi! Jake,

Have tried the code you provided. And since my ASL method ‘RTN0’ is simply return an argument ‘0’, I define OUTPUT_BUF_SIZE = (sizeof(ACPI_EVAL_OUTPUT_BUFFER) + (sizeof(ACPI_METHOD_ARGUMENT))) = 20 + 8 bytes.

Your code is successfully processed and return status = 0! However, we still cannot recognize the data retrieved from outputDesc and outputBuf :

outputDesc.Type = (1)
outputDesc.u.BufferType = (AeoB)
outputDesc.u.BufferType.Buffer = (AeoB)
outputDesc.u.BufferType.Buffer = (AeoB)
outputDesc.u.BufferType.Length = (28)
outputBuf[0] = (x=41), (c=A)
outputBuf[1] = (x=65), (c=e)
outputBuf[2] = (x=6f), (c=o)
outputBuf[3] = (x=42), (c=B)
outputBuf[4] = (x=14), (c=)
outputBuf[5] = (x=0), (c=outputBuf[6] = (x=0), (c=outputBuf[7] = (x=0), (c=outputBuf[8] = (x=1), (c=)
outputBuf[9] = (x=0), (c=outputBuf[10] = (x=0), (c=outputBuf[11] = (x=0), (c=outputBuf[12] = (x=0), (c=outputBuf[13] = (x=0), (c=outputBuf[14] = (x=4), (c=)
outputBuf[15] = (x=0), (c=outputBuf[16] = (x=0), (c=outputBuf[17] = (x=0), (c=outputBuf[18] = (x=0), (c=outputBuf[19] = (x=0), (c=outputBuf[20] = (x=0), (c=outputBuf[21] = (x=0), (c=outputBuf[22] = (x=0), (c=outputBuf[23] = (x=0), (c=outputBuf[24] = (x=0), (c=outputBuf[25] = (x=0), (c=outputBuf[26] = (x=0), (c=outputBuf[27] = (x=0), (c=outputBuf[28] = (x=52), (c=R)

(My outputBuf format :
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuf[%d] = (x=%x), (c=%c)\n”,i, outputBuf[i], outputBuf[i])); )

Could I have your comment again? Many thanks!

-tftu

I think you don’t really understand ASL/AML. There is no such thing in that
language as a generic “argument 0.” Every object has a type, and a method
can return any type of object. You need to know what type your object is.

Fortunately, the code told you.

As you know from reading my code, outputBuf is of type
ACPI_EVAL_OUTPUT_BUFFER. 12 bytes into that struct is ACPI_METHOD_ARGUMENT,
which I called acpiObj. So acpiObj starts at the byte that you’ve labeled
“c=outputBuf[12]”.

ACPI_METHOD_ARGUMENT itself has a Type field. That’s the type of your
object. In your case, that’s ACPI_METHOD_ARGUMENT_INTEGER. It also has a
Length field. Your output says that the returned integer was 4 bytes long.

(This is all just basic C programming, taken from the definitions of the
structs themselves, in acpiioctl.h. For instance, here’s
ACPI_METHOD_ARGUMENT. By casting, you can make the compiler do this work
for you.)

typedef struct _ACPI_METHOD_ARGUMENT {
USHORT Type;
USHORT DataLength;
union {
ULONG Argument;
UCHAR Data[ANYSIZE_ARRAY];
} DUMMYUNIONNAME;
} ACPI_METHOD_ARGUMENT;

Since you have a 4-byte integer, the value will be in *(PULONG)Data. In
your example below, that was 0.

Jake Oshins
Hyper-V I/O Architect
Windows Kernel Group

This post implies no warranties and confers no rights.


wrote in message news:xxxxx@ntdev…

Hi! Jake,

Have tried the code you provided. And since my ASL method ‘RTN0’ is
simply return an argument ‘0’, I define OUTPUT_BUF_SIZE =
(sizeof(ACPI_EVAL_OUTPUT_BUFFER) + (sizeof(ACPI_METHOD_ARGUMENT))) = 20

  • 8 bytes.

Your code is successfully processed and return status = 0! However, we
still cannot recognize the data retrieved from outputDesc and outputBuf :

outputDesc.Type = (1)
outputDesc.u.BufferType = (AeoB)
outputDesc.u.BufferType.Buffer = (AeoB)
outputDesc.u.BufferType.Buffer = (AeoB)
outputDesc.u.BufferType.Length = (28)
outputBuf[0] = (x=41), (c=A)
outputBuf[1] = (x=65), (c=e)
outputBuf[2] = (x=6f), (c=o)
outputBuf[3] = (x=42), (c=B)
outputBuf[4] = (x=14), (c=)
outputBuf[5] = (x=0), (c=outputBuf[6] = (x=0), (c=outputBuf[7] = (x=0),
(c=outputBuf[8] = (x=1), (c=)
outputBuf[9] = (x=0), (c=outputBuf[10] = (x=0), (c=outputBuf[11] = (x=0),
(c=outputBuf[12] = (x=0), (c=outputBuf[13] = (x=0), (c=outputBuf[14] =
(x=4), (c=)
outputBuf[15] = (x=0), (c=outputBuf[16] = (x=0), (c=outputBuf[17] = (x=0),
(c=outputBuf[18] = (x=0), (c=outputBuf[19] = (x=0), (c=outputBuf[20] =
(x=0), (c=outputBuf[21] = (x=0), (c=outputBuf[22] = (x=0), (c=outputBuf[23]
= (x=0), (c=outputBuf[24] = (x=0), (c=outputBuf[25] = (x=0),
(c=outputBuf[26] = (x=0), (c=outputBuf[27] = (x=0), (c=outputBuf[28] =
(x=52), (c=R)

(My outputBuf format :
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, “outputBuf[%d] = (x=%x), (c=%c)\n”,i,
outputBuf[i], outputBuf[i])); )

Could I have your comment again? Many thanks!

-tftu

Hi! Jake,

Yes, I’m new to ACPI/ASL/ALM/WDM/KMDF … But here I’d like to present my appreciation, I have got the ‘0’ as below dump per your advise:

*(PULONG)(((PACPI_EVAL_OUTPUT_BUFFER)outputBuf)->Argument[0].Data) = (0)

Now I can go further based on this result and methodology. Thanks again for your kind help.

-tftu