Author: phater
Date: Tue May 16 17:26:12 2017
New Revision: 74559
URL:
http://svn.reactos.org/svn/reactos?rev=74559&view=rev
Log:
[ACPI] Implement creating volatile registry keys for ACPI tables CORE-12942
Modified:
trunk/reactos/drivers/bus/acpi/busmgr/utils.c
trunk/reactos/drivers/bus/acpi/include/acpi_bus.h
trunk/reactos/drivers/bus/acpi/pnp.c
Modified: trunk/reactos/drivers/bus/acpi/busmgr/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/busmgr/ut…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/busmgr/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/busmgr/utils.c [iso-8859-1] Tue May 16 17:26:12 2017
@@ -24,6 +24,7 @@
*/
#include <precomp.h>
+#include <ntstrsafe.h>
#define NDEBUG
#include <debug.h>
@@ -369,4 +370,281 @@
return_ACPI_STATUS(status);
}
-
+NTSTATUS
+acpi_create_registry_table(HANDLE ParentKeyHandle, ACPI_TABLE_HEADER *OutTable, PCWSTR
KeyName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING HardwareKeyName, ValueName;
+ ANSI_STRING HardwareKeyNameA;
+ HANDLE KeyHandle = NULL, SubKeyHandle = NULL;
+ NTSTATUS Status;
+ char OemId[7] = { 0 }; /* exactly one byte more than ACPI_TABLE_HEADER->OemId */
+ char OemTableId[9] = { 0 }; /* exactly one byte more than
ACPI_TABLE_HEADER->OemTableId */
+ WCHAR OemRevision[9] = { 0 }; /* enough to accept hex DWORD */
+
+ C_ASSERT(sizeof(OemId) == RTL_FIELD_SIZE(ACPI_TABLE_HEADER, OemId) + 1);
+ C_ASSERT(sizeof(OemTableId) == RTL_FIELD_SIZE(ACPI_TABLE_HEADER, OemTableId) + 1);
+ /* Copy OEM data from the table */
+ RtlCopyMemory(OemId, OutTable->OemId, sizeof(OutTable->OemId));
+ RtlCopyMemory(OemTableId, OutTable->OemTableId, sizeof(OutTable->OemTableId));
+ /* Create table subkey */
+ RtlInitUnicodeString(&HardwareKeyName, KeyName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &HardwareKeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ ParentKeyHandle,
+ NULL);
+ Status = ZwCreateKey(&KeyHandle,
+ KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwCreateKey() for %ws failed (Status 0x%08lx)\n", KeyName,
Status);
+ return Status;
+ }
+
+ if (OutTable->OemRevision != 0)
+ {
+ /* We have OEM info in table, so create other OEM subkeys */
+ RtlInitAnsiString(&HardwareKeyNameA, OemId);
+ Status = RtlAnsiStringToUnicodeString(&HardwareKeyName,
&HardwareKeyNameA, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlAnsiStringToUnicodeString() for %s failed (Status
0x%08lx)\n", HardwareKeyNameA, Status);
+ return Status;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &HardwareKeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ KeyHandle,
+ NULL);
+ Status = ZwCreateKey(&SubKeyHandle,
+ KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ RtlFreeUnicodeString(&HardwareKeyName);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwCreateKey() for %s failed (Status 0x%08lx)\n",
HardwareKeyNameA, Status);
+ return Status;
+ }
+ KeyHandle = SubKeyHandle;
+
+ RtlInitAnsiString(&HardwareKeyNameA, OemTableId);
+ Status = RtlAnsiStringToUnicodeString(&HardwareKeyName,
&HardwareKeyNameA, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlAnsiStringToUnicodeString() for %s failed (Status
0x%08lx)\n", HardwareKeyNameA, Status);
+ return Status;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &HardwareKeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ KeyHandle,
+ NULL);
+ Status = ZwCreateKey(&SubKeyHandle,
+ KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ RtlFreeUnicodeString(&HardwareKeyName);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwCreateKey() for %s failed (Status 0x%08lx)\n",
HardwareKeyNameA, Status);
+ return Status;
+ }
+ KeyHandle = SubKeyHandle;
+
+ Status = RtlStringCbPrintfW(OemRevision,
+ sizeof(OemRevision),
+ L"%08X",
+ OutTable->OemRevision);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlStringCbPrintfW() for 0x%08lx failed (Status
0x%08lx)\n", OutTable->OemRevision, Status);
+ return Status;
+ }
+ RtlInitUnicodeString(&HardwareKeyName, OemRevision);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &HardwareKeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ KeyHandle,
+ NULL);
+ Status = ZwCreateKey(&SubKeyHandle,
+ KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwCreateKey() for %ws failed (Status 0x%08lx)\n", KeyName,
Status);
+ return Status;
+ }
+ KeyHandle = SubKeyHandle;
+ }
+ /* Table reg value name is always '00000000' */
+ RtlInitUnicodeString(&ValueName,
+ L"00000000");
+ Status = ZwSetValueKey(KeyHandle,
+ &ValueName,
+ 0,
+ REG_BINARY,
+ OutTable,
+ OutTable->Length);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwSetValueKey() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+acpi_create_volatile_registry_tables()
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING HardwareKeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\ACPI");
+ HANDLE KeyHandle = NULL;
+ NTSTATUS Status;
+ ACPI_STATUS AcpiStatus;
+ ACPI_TABLE_HEADER *OutTable;
+ ACPI_PHYSICAL_ADDRESS RsdpAddress;
+ ACPI_TABLE_RSDP *Rsdp;
+ ACPI_PHYSICAL_ADDRESS Address;
+ UINT32 TableEntrySize;
+
+ /* Create Main Hardware ACPI key*/
+ InitializeObjectAttributes(&ObjectAttributes,
+ &HardwareKeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ Status = ZwCreateKey(&KeyHandle,
+ KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwCreateKey() for ACPI failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+ /* Read DSDT table */
+ AcpiStatus = AcpiGetTable(ACPI_SIG_DSDT, 0, &OutTable);
+ if (ACPI_FAILURE(AcpiStatus))
+ {
+ DPRINT1("AcpiGetTable() for DSDT failed (Status 0x%08lx)\n",
AcpiStatus);
+ Status = STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ /* Dump DSDT table */
+ Status = acpi_create_registry_table(KeyHandle, OutTable, L"DSDT");
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("acpi_dump_table_to_registry() for DSDT failed (Status
0x%08lx)\n", Status);
+ goto done;
+ }
+ /* Read FACS table */
+ AcpiStatus = AcpiGetTable(ACPI_SIG_FACS, 0, &OutTable);
+ if (ACPI_FAILURE(AcpiStatus))
+ {
+ DPRINT1("AcpiGetTable() for FACS failed (Status 0x%08lx)\n",
AcpiStatus);
+ Status = STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ /* Dump FACS table */
+ Status = acpi_create_registry_table(KeyHandle, OutTable, L"FACS");
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("acpi_dump_table_to_registry() for FACS failed (Status
0x%08lx)\n", Status);
+ goto done;
+ }
+ /* Read FACS table */
+ AcpiStatus = AcpiGetTable(ACPI_SIG_FADT, 0, &OutTable);
+ if (ACPI_FAILURE(AcpiStatus))
+ {
+ DPRINT1("AcpiGetTable() for FADT failed (Status 0x%08lx)\n",
AcpiStatus);
+ Status = STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ /* Dump FADT table */
+ Status = acpi_create_registry_table(KeyHandle, OutTable, L"FADT");
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("acpi_dump_table_to_registry() for FADT failed (Status
0x%08lx)\n", Status);
+ goto done;
+ }
+ /* This is a rough copy from ACPICA reading of RSDT/XSDT and added to avoid patching
acpica */
+ RsdpAddress = AcpiOsGetRootPointer();
+ /* Map the entire RSDP and extract the address of the RSDT or XSDT */
+ Rsdp = AcpiOsMapMemory(RsdpAddress, sizeof(ACPI_TABLE_RSDP));
+ if (!Rsdp)
+ {
+ DPRINT1("AcpiOsMapMemory() failed\n");
+ Status = STATUS_NO_MEMORY;
+ goto done;
+ }
+ /* Use XSDT if present and not overridden. Otherwise, use RSDT */
+ if ((Rsdp->Revision > 1) &&
+ Rsdp->XsdtPhysicalAddress &&
+ !AcpiGbl_DoNotUseXsdt)
+ {
+ /*
+ * RSDP contains an XSDT (64-bit physical addresses). We must use
+ * the XSDT if the revision is > 1 and the XSDT pointer is present,
+ * as per the ACPI specification.
+ */
+ Address = (ACPI_PHYSICAL_ADDRESS)Rsdp->XsdtPhysicalAddress;
+ TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
+ }
+ else
+ {
+ /* Root table is an RSDT (32-bit physical addresses) */
+ Address = (ACPI_PHYSICAL_ADDRESS)Rsdp->RsdtPhysicalAddress;
+ TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
+ }
+ /*
+ * It is not possible to map more than one entry in some environments,
+ * so unmap the RSDP here before mapping other tables
+ */
+ AcpiOsUnmapMemory(Rsdp, sizeof(ACPI_TABLE_RSDP));
+ OutTable = AcpiOsMapMemory(Address, TableEntrySize);
+ if (!OutTable)
+ {
+ DPRINT1("AcpiOsMapMemory() failed\n");
+ Status = STATUS_NO_MEMORY;
+ goto done;
+ }
+ /* Dump RSDT table */
+ Status = acpi_create_registry_table(KeyHandle, OutTable, L"RSDT");
+ AcpiOsUnmapMemory(OutTable, TableEntrySize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("acpi_dump_table_to_registry() for RSDT failed (Status
0x%08lx)\n", Status);
+ }
+
+done:
+ ZwClose(KeyHandle);
+ return Status;
+}
Modified: trunk/reactos/drivers/bus/acpi/include/acpi_bus.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/include/a…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/include/acpi_bus.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/include/acpi_bus.h [iso-8859-1] Tue May 16 17:26:12
2017
@@ -57,6 +57,8 @@
ACPI_STRING pathname,
struct acpi_object_list *arguments,
struct acpi_handle_list *list);
+NTSTATUS
+acpi_create_volatile_registry_tables(void);
enum acpi_bus_removal_type {
ACPI_BUS_REMOVAL_NORMAL = 0,
Modified: trunk/reactos/drivers/bus/acpi/pnp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/pnp.c?rev…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/pnp.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/pnp.c [iso-8859-1] Tue May 16 17:26:12 2017
@@ -297,6 +297,12 @@
DPRINT1("Unable to AcpiLoadTables\n");
AcpiTerminate();
return STATUS_UNSUCCESSFUL;
+ }
+
+ status = acpi_create_volatile_registry_tables();
+ if (!NT_SUCCESS(status))
+ {
+ DPRINT1("Unable to create ACPI tables in registry\n");
}
DPRINT("Acpi subsystem init\n");