WIP move acpica to just the suspend syscall

Change-Id: I411583a3e21bd655efe146b011eb60dc8aa3effa
diff --git a/kernel/arch/x86/include/arch/x86/acpi.h b/kernel/arch/x86/include/arch/x86/acpi.h
index 7e32978..005a307 100644
--- a/kernel/arch/x86/include/arch/x86/acpi.h
+++ b/kernel/arch/x86/include/arch/x86/acpi.h
@@ -6,20 +6,16 @@
 
 #pragma once
 
-#include <acpica/acpi.h>
 #include <arch/x86/bootstrap16.h>
 #include <stdint.h>
 
-__BEGIN_CDECLS
-
 // Initiates a transition to the requested ACPI S-state.
 //
 // This must not be called before bootstrap16 is configured to handle the resume.
 //
 // This must be called from a kernel thread, unless it is a transition to
 // S5 (poweroff).  Failure to do so may result in loss of usermode register state.
-ACPI_STATUS x86_acpi_transition_s_state(struct x86_realmode_entry_data_registers* regs,
+extern "C"
+uint32_t x86_acpi_transition_s_state(struct x86_realmode_entry_data_registers* regs,
                                         uint8_t target_s_state,
                                         uint8_t sleep_type_a, uint8_t sleep_type_b);
-
-__END_CDECLS
diff --git a/kernel/lib/acpi_lite/acpi_lite.cpp b/kernel/lib/acpi_lite/acpi_lite.cpp
index f149862..29bc868 100644
--- a/kernel/lib/acpi_lite/acpi_lite.cpp
+++ b/kernel/lib/acpi_lite/acpi_lite.cpp
@@ -145,7 +145,11 @@
         }
 
         if (!memcmp(sig, header->sig, 4)) {
-            return header;
+            // validate the checksum
+            uint8_t c = acpi_checksum(header, header->length);
+            if (c == 0) {
+                return header;
+            }
         }
     }
 
diff --git a/kernel/lib/acpi_lite/include/lib/acpi_lite.h b/kernel/lib/acpi_lite/include/lib/acpi_lite.h
index e26f72d..c7867dd 100644
--- a/kernel/lib/acpi_lite/include/lib/acpi_lite.h
+++ b/kernel/lib/acpi_lite/include/lib/acpi_lite.h
@@ -51,6 +51,17 @@
     };
 } __PACKED;
 
+struct acpi_generic_address_ {
+    uint8_t address_space_id;
+    uint8_t register_bit_width;
+    uint8_t register_bit_offset;
+    uint8_t access_size;
+    uint64_t address;
+} __PACKED;
+
+#define ACPI_ADDR_SPACE_MEMORY  0
+#define ACPI_ADDR_SPACE_IO      1
+
 #define ACPI_RSDT_SIG "RSDT"
 #define ACPI_XSDT_SIG "XSDT"
 
@@ -68,14 +79,7 @@
     uint8_t length;
 } __PACKED;
 
-struct acpi_generic_address_ {
-    uint8_t address_space_id;
-    uint8_t register_bit_width;
-    uint8_t register_bit_offset;
-    uint8_t access_size;
-    uint64_t address;
-} __PACKED;
-
+#define ACPI_HPET_SIG "HPET"
 struct acpi_hpet_table {
     acpi_sdt_header header;
     uint32_t id;
@@ -95,7 +99,7 @@
 // MADT table describes processors and interrupt controllers
 
 // type 0: local apic
-// #define ACPI_MADT_TYPE_LOCAL_APIC 0
+#define ACPI_MADT_TYPE_LOCAL_APIC 0
 struct acpi_madt_local_apic_entry {
     acpi_sub_table_header header;
     uint8_t processor_id;
@@ -106,7 +110,7 @@
 #define ACPI_MADT_FLAG_ENABLED 0x1
 
 // type 1: io apic
-// #define ACPI_MADT_TYPE_IO_APIC 1
+#define ACPI_MADT_TYPE_IO_APIC 1
 struct acpi_madt_io_apic_entry {
     acpi_sub_table_header header;
     uint8_t io_apic_id;
@@ -116,7 +120,7 @@
 } __PACKED;
 
 // type 2: interrupt source override
-// #define ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE 2
+#define ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE 2
 struct acpi_madt_int_source_override_entry {
     acpi_sub_table_header header;
     uint8_t bus;
diff --git a/kernel/platform/pc/acpi.cpp b/kernel/platform/pc/acpi.cpp
index 8cf93bc..721658a 100644
--- a/kernel/platform/pc/acpi.cpp
+++ b/kernel/platform/pc/acpi.cpp
@@ -16,68 +16,6 @@
 
 #define LOCAL_TRACE 1
 
-#include <acpica/acpi.h>
-
-#if 0
-#define ACPI_MAX_INIT_TABLES 32
-static ACPI_TABLE_DESC acpi_tables[ACPI_MAX_INIT_TABLES];
-static bool acpi_initialized = false;
-
-/**
- * @brief  Initialize early-access ACPI tables
- *
- * This function enables *only* the ACPICA Table Manager subsystem.
- * The rest of the ACPI subsystem will remain uninitialized.
- */
-void platform_init_acpi_tables(uint level) {
-    DEBUG_ASSERT(!acpi_initialized);
-
-    ACPI_STATUS status;
-    status = AcpiInitializeTables(acpi_tables, ACPI_MAX_INIT_TABLES, FALSE);
-
-    if (status == AE_NOT_FOUND) {
-        TRACEF("WARNING: could not find ACPI tables\n");
-        return;
-    } else if (status == AE_NO_MEMORY) {
-        TRACEF("WARNING: could not initialize ACPI tables\n");
-        return;
-    } else if (status != AE_OK) {
-        TRACEF("WARNING: could not initialize ACPI tables for unknown reason\n");
-        return;
-    }
-
-    acpi_initialized = true;
-    LTRACEF("ACPI tables initialized\n");
-}
-
-/* initialize ACPI tables as soon as we have a working VM */
-LK_INIT_HOOK(acpi_tables, &platform_init_acpi_tables, LK_INIT_LEVEL_VM + 1);
-
-static zx_status_t acpi_get_madt_record_limits(uintptr_t* start, uintptr_t* end) {
-    ACPI_TABLE_HEADER* table = NULL;
-    ACPI_STATUS status = AcpiGetTable((char*)ACPI_SIG_MADT, 1, &table);
-    if (status != AE_OK) {
-        TRACEF("could not find MADT\n");
-        return ZX_ERR_NOT_FOUND;
-    }
-    ACPI_TABLE_MADT* madt = (ACPI_TABLE_MADT*)table;
-    uintptr_t records_start = ((uintptr_t)madt) + sizeof(*madt);
-    uintptr_t records_end = ((uintptr_t)madt) + madt->Header.Length;
-    if (records_start >= records_end) {
-        TRACEF("MADT wraps around address space\n");
-        return ZX_ERR_INTERNAL;
-    }
-    // Shouldn't be too many records
-    if (madt->Header.Length > 4096) {
-        TRACEF("MADT suspiciously long: %u\n", madt->Header.Length);
-        return ZX_ERR_INTERNAL;
-    }
-    *start = records_start;
-    *end = records_end;
-    return ZX_OK;
-}
-#endif
-
 /* @brief Enumerate all functioning CPUs and their APIC IDs
  *
  * If apic_ids is NULL, just returns the number of logical processors
@@ -182,7 +120,7 @@
     }
 
     uint32_t count = 0;
-    acpi_process_madt_entries_etc(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+    acpi_process_madt_entries_etc(ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE,
             [isos, &count, len](const void *_entry, size_t entry_len) {
         auto entry = static_cast<const acpi_madt_int_source_override_entry*>(_entry);
 
@@ -241,34 +179,34 @@
  * @return ZX_OK on success.
  */
 zx_status_t platform_find_hpet(struct acpi_hpet_descriptor* hpet) {
-#if 0
-    ACPI_TABLE_HEADER* table = NULL;
-    ACPI_STATUS status = AcpiGetTable((char*)ACPI_SIG_HPET, 1, &table);
-    if (status != AE_OK) {
-        TRACEF("could not find HPET\n");
-        return ZX_ERR_NOT_FOUND;
-    }
-    ACPI_TABLE_HPET* hpet_tbl = (ACPI_TABLE_HPET*)table;
-    if (hpet_tbl->Header.Length != sizeof(ACPI_TABLE_HPET)) {
-        TRACEF("Unexpected HPET table length\n");
+    const acpi_sdt_header* header = acpi_get_table_by_sig(ACPI_HPET_SIG);
+    if (!header) {
         return ZX_ERR_NOT_FOUND;
     }
 
-    hpet->minimum_tick = hpet_tbl->MinimumTick;
-    hpet->sequence = hpet_tbl->Sequence;
-    hpet->address = hpet_tbl->Address.Address;
-    switch (hpet_tbl->Address.SpaceId) {
-    case ACPI_ADR_SPACE_SYSTEM_IO:
+    if (header->revision != 1) {
+        return ZX_ERR_NOT_FOUND;
+    }
+
+    if (header->length != sizeof(acpi_hpet_table)) {
+        return ZX_ERR_NOT_FOUND;
+    }
+
+    const acpi_hpet_table* table = reinterpret_cast<const acpi_hpet_table*>(header);
+
+    hpet->minimum_tick = table->minimum_tick;
+    hpet->sequence = table->sequence;
+    hpet->address = table->address.address;
+    switch (table->address.address_space_id) {
+    case ACPI_ADDR_SPACE_IO:
         hpet->port_io = true;
         break;
-    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+    case ACPI_ADDR_SPACE_MEMORY:
         hpet->port_io = false;
         break;
     default:
         return ZX_ERR_NOT_SUPPORTED;
     }
+    TRACE;
     return ZX_OK;
-#endif
-
-    return ZX_ERR_NOT_SUPPORTED;
 }
diff --git a/kernel/platform/pc/hpet.cpp b/kernel/platform/pc/hpet.cpp
index e58fc02..f96e404 100644
--- a/kernel/platform/pc/hpet.cpp
+++ b/kernel/platform/pc/hpet.cpp
@@ -105,6 +105,10 @@
     _hpet_ticks_per_ms = 1000000000000ULL / tick_period_in_fs;
     min_ticks_ahead = 100000000ULL / tick_period_in_fs;
     hpet_present = true;
+
+    dprintf(INFO, "HPET: detected at %#" PRIx64 " ticks per ms %" PRIu64 " num timers %hhu\n",
+            hpet_desc.address, _hpet_ticks_per_ms, num_timers);
+
     return;
 
 fail:
diff --git a/kernel/platform/pc/rules.mk b/kernel/platform/pc/rules.mk
index c4ed207..04397c4 100644
--- a/kernel/platform/pc/rules.mk
+++ b/kernel/platform/pc/rules.mk
@@ -28,7 +28,6 @@
     $(LOCAL_DIR)/timer.cpp \
 
 MODULE_DEPS += \
-    third_party/lib/acpica \
     third_party/lib/cksum \
     kernel/lib/acpi_lite \
     kernel/lib/cbuf \
diff --git a/kernel/syscalls/rules.mk b/kernel/syscalls/rules.mk
index 955fca8..d576975 100644
--- a/kernel/syscalls/rules.mk
+++ b/kernel/syscalls/rules.mk
@@ -47,6 +47,8 @@
 MODULE_SRCS += $(LOCAL_DIR)/system_x86.cpp \
 	       $(LOCAL_DIR)/ddk_x86.cpp \
 
+MODULE_DEPS += third_party/lib/acpica
+
 else ifeq ($(ARCH),arm64)
 MODULE_SRCS += $(LOCAL_DIR)/system_arm64.cpp \
 	       $(LOCAL_DIR)/ddk_arm64.cpp \
diff --git a/kernel/syscalls/system_x86.cpp b/kernel/syscalls/system_x86.cpp
index 9e84c2a..1a96c58 100644
--- a/kernel/syscalls/system_x86.cpp
+++ b/kernel/syscalls/system_x86.cpp
@@ -11,6 +11,7 @@
 #include <fbl/auto_call.h>
 #include <inttypes.h>
 #include <kernel/timer.h>
+#include <lk/init.h>
 #include <platform.h>
 #include <trace.h>
 #include <vm/vm_aspace.h>
@@ -28,6 +29,39 @@
 
 namespace {
 
+#define ACPI_MAX_INIT_TABLES 32
+//static ACPI_TABLE_DESC acpi_tables[ACPI_MAX_INIT_TABLES];
+static bool acpi_initialized = false;
+
+/**
+ * @brief  Initialize early-access ACPI tables
+ *
+ * This function enables *only* the ACPICA Table Manager subsystem.
+ * The rest of the ACPI subsystem will remain uninitialized.
+ */
+void init_acpica_tables(uint level) {
+    DEBUG_ASSERT(!acpi_initialized);
+
+    ACPI_STATUS status;
+    status = AcpiInitializeTables(nullptr, ACPI_MAX_INIT_TABLES, FALSE);
+
+    if (status == AE_NOT_FOUND) {
+        TRACEF("WARNING: could not find ACPI tables\n");
+        return;
+    } else if (status == AE_NO_MEMORY) {
+        TRACEF("WARNING: could not initialize ACPI tables\n");
+        return;
+    } else if (status != AE_OK) {
+        TRACEF("WARNING: could not initialize ACPI tables for unknown reason\n");
+        return;
+    }
+
+    acpi_initialized = true;
+    LTRACEF("ACPI tables initialized\n");
+}
+
+LK_INIT_HOOK(acpica_tables, &init_acpica_tables, LK_INIT_LEVEL_THREADING);
+
 // This thread performs the work for suspend/resume.  We use a separate thread
 // rather than the invoking thread to let us lean on the context switch code
 // path to persist all of the usermode thread state that is not saved on a plain
@@ -151,6 +185,10 @@
 }
 
 zx_status_t acpi_transition_s_state(const zx_system_powerctl_arg_t* arg) {
+    if (!acpi_initialized) {
+        return ZX_ERR_BAD_STATE;
+    }
+
     uint8_t target_s_state = arg->acpi_transition_s_state.target_s_state;
     uint8_t sleep_type_a = arg->acpi_transition_s_state.sleep_type_a;
     uint8_t sleep_type_b = arg->acpi_transition_s_state.sleep_type_b;
@@ -192,10 +230,10 @@
         DEBUG_ASSERT(target_s_state == 5);
         arch_disable_ints();
 
-        ACPI_STATUS acpi_status = x86_acpi_transition_s_state(&regs, target_s_state,
+        auto acpi_status = x86_acpi_transition_s_state(&regs, target_s_state,
                                                               sleep_type_a, sleep_type_b);
         arch_enable_ints();
-        if (acpi_status != AE_OK) {
+        if (acpi_status != 0) {
             return ZX_ERR_INTERNAL;
         }
     }