Justin Timbersaw
Justin Timbersaw

Reputation: 113

Call ACPI control method failed from kernel mode driver with status = STATUS_INVALID_PARAMETER

I have a kernel mode driver that handles an acpi device called \_SB.SECO has a custom control method called FIRE. In ACPI UEFI, I define it as:

Scope (\_SB_)
{
      Device (SECO)
      {
          Name (_HID, "TEST2412")   // Hardware ID
          Name (_UID, 0x0)        // Unique ID

          Method (_STA, 0, NotSerialized)
          {
              Return (0x0F) // Device is present and enabled
          }

          Method (FIRE, 0, NotSerialized)
          {
              Notify (\_SB.FIRS, 0x80) // notify another device
          }
      }
}

In Device Manager, I can see the Physical Device Object name for SECO is \Device\00000071. So from my driver, I get the object pointer to it:

NTSTATUS GetAcpiDevice(PDEVICE_OBJECT* pAcpiDevice, PFILE_OBJECT* pFileObject) {
    UNICODE_STRING AcpiDeviceName;
    RtlInitUnicodeString(&AcpiDeviceName, L"\\Device\\00000071");

    return IoGetDeviceObjectPointer(&AcpiDeviceName, FILE_ALL_ACCESS, pFileObject, pAcpiDevice);
}

After getting device object, I build an IRP to evaluate FIRE control method and send it to ACPI driver, which will handle the IRP for my device:

NTSTATUS CallAcpiMethod(PDEVICE_OBJECT pAcpiDevice) {
    KdPrint(("CallAcpiMethod enter\n"));
    ACPI_EVAL_INPUT_BUFFER inputBuffer;
    ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    IO_STATUS_BLOCK ioStatus;
    KEVENT event;
    PIRP irp;

    // Initialize input buffer for method call
    inputBuffer.MethodNameAsUlong = (ULONG)('ERIF');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

    // Create event for IRP completion
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    // Build IRP for IOCTL_ACPI_EVAL_METHOD
    irp = IoBuildDeviceIoControlRequest(
        IOCTL_ACPI_EVAL_METHOD,
        pAcpiDevice,
        &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER),
        &outputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER),
        FALSE, &event, &ioStatus);
    KdPrint(("IRP Address: %p\n", irp));
    if (!irp) {
        KdPrint(("failed to create IRP\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // Send request
    NTSTATUS status = IoCallDriver(pAcpiDevice, irp);
    if (status == STATUS_PENDING) {
        KdPrint(("IoCallDriver pending status=%ld\n", status));
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }

    KdPrint(("CallAcpiMethod exit status=%ld\n", status));
    return status;
}

The log indicates that IRP was successfully created, but the status from IoCallDriver is -1073741811 (STATUS_INVALID_PARAMETER).

How can I fix this issue?

Upvotes: 0

Views: 61

Answers (0)

Related Questions