bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/3] i386: use ACPI to power off the machine


From: Justus Winter
Subject: [PATCH 3/3] i386: use ACPI to power off the machine
Date: Sat, 3 May 2014 01:33:14 +0200

This is a mostly verbatim copy of acpihalt.c from GRUB2 with a little
bit of glue code.

* i386/Makefrag.am (libkernel_a_SOURCES): Add the new files.
* i386/grub/acpi.h: Verbatim copy from GRUB2.
* i386/grub/compiler.h: Likewise.
* i386/grub/cpu/io.h: Likewise.
* i386/grub/cpu/time.h: Likewise.
* i386/grub/cpu/types.h: Likewise.
* i386/grub/err.h: Likewise.
* i386/grub/misc.h: Likewise.
* i386/grub/mm.h: Likewise.
* i386/grub/symbol.h: Likewise.
* i386/grub/time.h: Likewise.
* i386/grub/types.h: Likewise.
* i386/i386at/acpi.c: Likewise.
* i386/i386at/acpihalt.c: Likewise.
(grub_acpi_halt): Map physical addresses.
* i386/i386at/acpihalt.h: New file.
* i386/grub/glue.h: Some glue macros.
* i386/grub/i18n.h: Stub out i18n.
* i386/i386at/grub_glue.c: Some glue code.
* i386/i386at/model_dep.c (halt_all_cpus): Use grub_acpi_halt.
---
 i386/Makefrag.am        |  19 ++
 i386/grub/acpi.h        | 220 +++++++++++++++++++++
 i386/grub/compiler.h    |  51 +++++
 i386/grub/cpu/io.h      |  72 +++++++
 i386/grub/cpu/time.h    |  29 +++
 i386/grub/cpu/types.h   |  33 ++++
 i386/grub/err.h         |  96 +++++++++
 i386/grub/glue.h        |  31 +++
 i386/grub/i18n.h        |  25 +++
 i386/grub/misc.h        | 517 ++++++++++++++++++++++++++++++++++++++++++++++++
 i386/grub/mm.h          |  77 ++++++++
 i386/grub/symbol.h      |  72 +++++++
 i386/grub/time.h        |  46 +++++
 i386/grub/types.h       | 325 ++++++++++++++++++++++++++++++
 i386/i386at/acpi.c      |  82 ++++++++
 i386/i386at/acpihalt.c  | 409 ++++++++++++++++++++++++++++++++++++++
 i386/i386at/acpihalt.h  |  23 +++
 i386/i386at/grub_glue.c |  67 +++++++
 i386/i386at/model_dep.c |   2 +
 19 files changed, 2196 insertions(+)
 create mode 100644 i386/grub/acpi.h
 create mode 100644 i386/grub/compiler.h
 create mode 100644 i386/grub/cpu/io.h
 create mode 100644 i386/grub/cpu/time.h
 create mode 100644 i386/grub/cpu/types.h
 create mode 100644 i386/grub/err.h
 create mode 100644 i386/grub/glue.h
 create mode 100644 i386/grub/i18n.h
 create mode 100644 i386/grub/misc.h
 create mode 100644 i386/grub/mm.h
 create mode 100644 i386/grub/symbol.h
 create mode 100644 i386/grub/time.h
 create mode 100644 i386/grub/types.h
 create mode 100644 i386/i386at/acpi.c
 create mode 100644 i386/i386at/acpihalt.c
 create mode 100644 i386/i386at/acpihalt.h
 create mode 100644 i386/i386at/grub_glue.c

diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index cac2267..4dd6a9f 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -55,6 +55,25 @@ libkernel_a_SOURCES += \
        i386/i386at/pic_isa.c \
        i386/i386at/rtc.c \
        i386/i386at/rtc.h
+
+libkernel_a_SOURCES += \
+       i386/i386at/acpihalt.c \
+       i386/i386at/acpihalt.h \
+       i386/i386at/acpi.c \
+       i386/i386at/grub_glue.c \
+       i386/grub/err.h \
+       i386/grub/cpu/io.h \
+       i386/grub/cpu/types.h \
+       i386/grub/cpu/time.h \
+       i386/grub/mm.h \
+       i386/grub/acpi.h \
+       i386/grub/symbol.h \
+       i386/grub/misc.h \
+       i386/grub/types.h \
+       i386/grub/time.h \
+       i386/grub/i18n.h \
+       i386/grub/compiler.h \
+       i386/grub/glue.h
 endif
 
 #
diff --git a/i386/grub/acpi.h b/i386/grub/acpi.h
new file mode 100644
index 0000000..2ac2bd6
--- /dev/null
+++ b/i386/grub/acpi.h
@@ -0,0 +1,220 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ACPI_HEADER
+#define GRUB_ACPI_HEADER       1
+
+#ifndef GRUB_DSDT_TEST
+#include <grub/types.h>
+#include <grub/err.h>
+#endif
+
+#define GRUB_RSDP_SIGNATURE "RSD PTR "
+#define GRUB_RSDP_SIGNATURE_SIZE 8
+
+struct grub_acpi_rsdp_v10
+{
+  grub_uint8_t signature[GRUB_RSDP_SIGNATURE_SIZE];
+  grub_uint8_t checksum;
+  grub_uint8_t oemid[6];
+  grub_uint8_t revision;
+  grub_uint32_t rsdt_addr;
+} GRUB_PACKED;
+
+struct grub_acpi_rsdp_v20
+{
+  struct grub_acpi_rsdp_v10 rsdpv1;
+  grub_uint32_t length;
+  grub_uint64_t xsdt_addr;
+  grub_uint8_t checksum;
+  grub_uint8_t reserved[3];
+} GRUB_PACKED;
+
+struct grub_acpi_table_header
+{
+  grub_uint8_t signature[4];
+  grub_uint32_t length;
+  grub_uint8_t revision;
+  grub_uint8_t checksum;
+  grub_uint8_t oemid[6];
+  grub_uint8_t oemtable[8];
+  grub_uint32_t oemrev;
+  grub_uint8_t creator_id[4];
+  grub_uint32_t creator_rev;
+} GRUB_PACKED;
+
+#define GRUB_ACPI_FADT_SIGNATURE "FACP"
+
+struct grub_acpi_fadt
+{
+  struct grub_acpi_table_header hdr;
+  grub_uint32_t facs_addr;
+  grub_uint32_t dsdt_addr;
+  grub_uint8_t somefields1[20];
+  grub_uint32_t pm1a;
+  grub_uint8_t somefields2[64];
+  grub_uint64_t facs_xaddr;
+  grub_uint64_t dsdt_xaddr;
+  grub_uint8_t somefields3[96];
+} GRUB_PACKED;
+
+#define GRUB_ACPI_MADT_SIGNATURE "APIC"
+
+struct grub_acpi_madt_entry_header
+{
+  grub_uint8_t type;
+  grub_uint8_t len;
+};
+
+struct grub_acpi_madt
+{
+  struct grub_acpi_table_header hdr;
+  grub_uint32_t lapic_addr;
+  grub_uint32_t flags;
+  struct grub_acpi_madt_entry_header entries[0];
+};
+
+enum
+  {
+    GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC = 0,
+    GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC = 1,
+    GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2,
+    GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI = 4,
+    GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6,
+    GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7,
+    GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8
+  };
+
+struct grub_acpi_madt_entry_lapic
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t acpiid;
+  grub_uint8_t apicid;
+  grub_uint32_t flags;
+};
+
+struct grub_acpi_madt_entry_ioapic
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t id;
+  grub_uint8_t pad;
+  grub_uint32_t address;
+  grub_uint32_t global_sys_interrupt;
+};
+
+struct grub_acpi_madt_entry_interrupt_override
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t bus;
+  grub_uint8_t source;
+  grub_uint32_t global_sys_interrupt;
+  grub_uint16_t flags;
+} GRUB_PACKED;
+
+
+struct grub_acpi_madt_entry_lapic_nmi
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t acpiid;
+  grub_uint16_t flags;
+  grub_uint8_t lint;
+} GRUB_PACKED;
+
+struct grub_acpi_madt_entry_sapic
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t id;
+  grub_uint8_t pad;
+  grub_uint32_t global_sys_interrupt_base;
+  grub_uint64_t addr;
+};
+
+struct grub_acpi_madt_entry_lsapic
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint8_t cpu_id;
+  grub_uint8_t id;
+  grub_uint8_t eid;
+  grub_uint8_t pad[3];
+  grub_uint32_t flags;
+  grub_uint32_t cpu_uid;
+  grub_uint8_t cpu_uid_str[0];
+};
+
+struct grub_acpi_madt_entry_platform_int_source
+{
+  struct grub_acpi_madt_entry_header hdr;
+  grub_uint16_t flags;
+  grub_uint8_t inttype;
+  grub_uint8_t cpu_id;
+  grub_uint8_t cpu_eid;
+  grub_uint8_t sapic_vector;
+  grub_uint32_t global_sys_int;
+  grub_uint32_t src_flags;
+};
+
+enum
+  {
+    GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED = 1
+  };
+
+#ifndef GRUB_DSDT_TEST
+struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void);
+struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void);
+struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void);
+struct grub_acpi_rsdp_v20 *grub_machine_acpi_get_rsdpv2 (void);
+grub_uint8_t grub_byte_checksum (void *base, grub_size_t size);
+
+grub_err_t grub_acpi_create_ebda (void);
+
+void grub_acpi_halt (void);
+#endif
+
+#define GRUB_ACPI_SLP_EN (1 << 13)
+#define GRUB_ACPI_SLP_TYP_OFFSET 10
+
+enum
+  {
+    GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1,
+    GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a,
+    GRUB_ACPI_OPCODE_WORD_CONST = 0x0b,
+    GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c,
+    GRUB_ACPI_OPCODE_STRING_CONST = 0x0d,
+    GRUB_ACPI_OPCODE_SCOPE = 0x10,
+    GRUB_ACPI_OPCODE_BUFFER = 0x11,
+    GRUB_ACPI_OPCODE_PACKAGE = 0x12,
+    GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b,
+    GRUB_ACPI_OPCODE_CREATE_WORD_FIELD = 0x8b,
+    GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD = 0x8c,
+    GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff
+  };
+enum
+  {
+    GRUB_ACPI_EXTOPCODE_MUTEX = 0x01,
+    GRUB_ACPI_EXTOPCODE_EVENT_OP = 0x02,
+    GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80,
+    GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81,
+    GRUB_ACPI_EXTOPCODE_DEVICE_OP = 0x82,
+    GRUB_ACPI_EXTOPCODE_PROCESSOR_OP = 0x83,
+    GRUB_ACPI_EXTOPCODE_POWER_RES_OP = 0x84,
+    GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP = 0x85,
+    GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP = 0x86,
+    GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP = 0x87,
+  };
+
+#endif /* ! GRUB_ACPI_HEADER */
diff --git a/i386/grub/compiler.h b/i386/grub/compiler.h
new file mode 100644
index 0000000..c9e1d7a
--- /dev/null
+++ b/i386/grub/compiler.h
@@ -0,0 +1,51 @@
+/* compiler.h - macros for various compiler features */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014  Free Software 
Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_COMPILER_HEADER
+#define GRUB_COMPILER_HEADER   1
+
+/* GCC version checking borrowed from glibc. */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#  define GNUC_PREREQ(maj,min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+#  define GNUC_PREREQ(maj,min) 0
+#endif
+
+/* Does this compiler support compile-time error attributes? */
+#if GNUC_PREREQ(4,3)
+#  define ATTRIBUTE_ERROR(msg) \
+       __attribute__ ((__error__ (msg)))
+#else
+#  define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
+#endif
+
+#if GNUC_PREREQ(4,4)
+#  define GNU_PRINTF gnu_printf
+#else
+#  define GNU_PRINTF printf
+#endif
+
+#if GNUC_PREREQ(3,4)
+#  define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+#else
+#  define WARN_UNUSED_RESULT
+#endif
+
+#endif /* ! GRUB_COMPILER_HEADER */
diff --git a/i386/grub/cpu/io.h b/i386/grub/cpu/io.h
new file mode 100644
index 0000000..ae12a3e
--- /dev/null
+++ b/i386/grub/cpu/io.h
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1996,2000,2002,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on sys/io.h from GNU libc. */
+
+#ifndef        GRUB_IO_H
+#define        GRUB_IO_H       1
+
+typedef unsigned short int grub_port_t;
+
+static __inline unsigned char
+grub_inb (unsigned short int port)
+{
+  unsigned char _v;
+
+  __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline unsigned short int
+grub_inw (unsigned short int port)
+{
+  unsigned short _v;
+
+  __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline unsigned int
+grub_inl (unsigned short int port)
+{
+  unsigned int _v;
+
+  __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline void
+grub_outb (unsigned char value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port));
+}
+
+static __inline void
+grub_outw (unsigned short int value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port));
+
+}
+
+static __inline void
+grub_outl (unsigned int value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port));
+}
+
+#endif /* _SYS_IO_H */
diff --git a/i386/grub/cpu/time.h b/i386/grub/cpu/time.h
new file mode 100644
index 0000000..842882c
--- /dev/null
+++ b/i386/grub/cpu/time.h
@@ -0,0 +1,29 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: this can't work until we handle interrupts.  */
+/*  __asm__ __volatile__ ("hlt"); */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/i386/grub/cpu/types.h b/i386/grub/cpu/types.h
new file mode 100644
index 0000000..c20063f
--- /dev/null
+++ b/i386/grub/cpu/types.h
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2006,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P      4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG                4
+
+/* i386 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_HAVE_UNALIGNED_ACCESS 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/i386/grub/err.h b/i386/grub/err.h
new file mode 100644
index 0000000..1590c68
--- /dev/null
+++ b/i386/grub/err.h
@@ -0,0 +1,96 @@
+/* err.h - error numbers and prototypes */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2007,2008 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ERR_HEADER
+#define GRUB_ERR_HEADER        1
+
+#include <grub/symbol.h>
+
+#define GRUB_MAX_ERRMSG                256
+
+typedef enum
+  {
+    GRUB_ERR_NONE = 0,
+    GRUB_ERR_TEST_FAILURE,
+    GRUB_ERR_BAD_MODULE,
+    GRUB_ERR_OUT_OF_MEMORY,
+    GRUB_ERR_BAD_FILE_TYPE,
+    GRUB_ERR_FILE_NOT_FOUND,
+    GRUB_ERR_FILE_READ_ERROR,
+    GRUB_ERR_BAD_FILENAME,
+    GRUB_ERR_UNKNOWN_FS,
+    GRUB_ERR_BAD_FS,
+    GRUB_ERR_BAD_NUMBER,
+    GRUB_ERR_OUT_OF_RANGE,
+    GRUB_ERR_UNKNOWN_DEVICE,
+    GRUB_ERR_BAD_DEVICE,
+    GRUB_ERR_READ_ERROR,
+    GRUB_ERR_WRITE_ERROR,
+    GRUB_ERR_UNKNOWN_COMMAND,
+    GRUB_ERR_INVALID_COMMAND,
+    GRUB_ERR_BAD_ARGUMENT,
+    GRUB_ERR_BAD_PART_TABLE,
+    GRUB_ERR_UNKNOWN_OS,
+    GRUB_ERR_BAD_OS,
+    GRUB_ERR_NO_KERNEL,
+    GRUB_ERR_BAD_FONT,
+    GRUB_ERR_NOT_IMPLEMENTED_YET,
+    GRUB_ERR_SYMLINK_LOOP,
+    GRUB_ERR_BAD_COMPRESSED_DATA,
+    GRUB_ERR_MENU,
+    GRUB_ERR_TIMEOUT,
+    GRUB_ERR_IO,
+    GRUB_ERR_ACCESS_DENIED,
+    GRUB_ERR_EXTRACTOR,
+    GRUB_ERR_NET_BAD_ADDRESS,
+    GRUB_ERR_NET_ROUTE_LOOP,
+    GRUB_ERR_NET_NO_ROUTE,
+    GRUB_ERR_NET_NO_ANSWER,
+    GRUB_ERR_NET_NO_CARD,
+    GRUB_ERR_WAIT,
+    GRUB_ERR_BUG,
+    GRUB_ERR_NET_PORT_CLOSED,
+    GRUB_ERR_NET_INVALID_RESPONSE,
+    GRUB_ERR_NET_UNKNOWN_ERROR,
+    GRUB_ERR_NET_PACKET_TOO_BIG,
+    GRUB_ERR_NET_NO_DOMAIN,
+    GRUB_ERR_EOF,
+    GRUB_ERR_BAD_SIGNATURE
+  }
+grub_err_t;
+
+struct grub_error_saved
+{
+  grub_err_t grub_errno;
+  char errmsg[GRUB_MAX_ERRMSG];
+};
+
+extern grub_err_t EXPORT_VAR(grub_errno);
+extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG];
+
+grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...);
+void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_error_push) (void);
+int EXPORT_FUNC(grub_error_pop) (void);
+void EXPORT_FUNC(grub_print_error) (void);
+extern int EXPORT_VAR(grub_err_printed_errors);
+int grub_err_printf (const char *fmt, ...)
+     __attribute__ ((format (__printf__, 1, 2)));
+
+#endif /* ! GRUB_ERR_HEADER */
diff --git a/i386/grub/glue.h b/i386/grub/glue.h
new file mode 100644
index 0000000..e1c62eb
--- /dev/null
+++ b/i386/grub/glue.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Free Software Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GRUB_GLUE_H
+#define _GRUB_GLUE_H
+
+#define GRUB_FILE __FILE__
+#define grub_memcmp memcmp
+#define grub_printf printf
+#define grub_puts_ puts
+
+#include <mach/mach_types.h>
+#include <i386/vm_param.h>
+
+vm_offset_t io_map_cached(vm_offset_t phys_addr, vm_size_t size);
+
+#endif /* _GRUB_GLUE_H */
diff --git a/i386/grub/i18n.h b/i386/grub/i18n.h
new file mode 100644
index 0000000..8b53357
--- /dev/null
+++ b/i386/grub/i18n.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Free Software Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GRUB_I18N_H
+#define _GRUB_I18N_H
+
+/* No i18n please.  */
+#define _(x) x
+#define N_(x) x
+
+#endif /* _GRUB_I18N_H */
diff --git a/i386/grub/misc.h b/i386/grub/misc.h
new file mode 100644
index 0000000..c6cd456
--- /dev/null
+++ b/i386/grub/misc.h
@@ -0,0 +1,517 @@
+/* misc.h - prototypes for misc functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010  Free Software 
Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MISC_HEADER
+#define GRUB_MISC_HEADER       1
+
+#include <stdarg.h>
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/i18n.h>
+#include <grub/compiler.h>
+
+#define ALIGN_UP(addr, align) \
+       ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
+#define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 
1))
+#define ALIGN_DOWN(addr, align) \
+       ((addr) & ~((typeof (addr)) align - 1))
+#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
+#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
+
+#define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, 
condition, __VA_ARGS__)
+
+void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
+char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
+
+static inline char *
+grub_strncpy (char *dest, const char *src, int c)
+{
+  char *p = dest;
+
+  while ((*p++ = *src++) != '\0' && --c)
+    ;
+
+  return dest;
+}
+
+static inline char *
+grub_stpcpy (char *dest, const char *src)
+{
+  char *d = dest;
+  const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+
+/* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
+static inline void *
+grub_memcpy (void *dest, const void *src, grub_size_t n)
+{
+  return grub_memmove (dest, src, n);
+}
+
+#if defined (__APPLE__) && defined(__i386__) && !defined (GRUB_UTIL)
+#define GRUB_BUILTIN_ATTR  __attribute__ ((regparm(0)))
+#else
+#define GRUB_BUILTIN_ATTR
+#endif
+
+#if defined(__x86_64__) && !defined (GRUB_UTIL)
+#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (__MINGW64__)
+#define GRUB_ASM_ATTR __attribute__ ((sysv_abi))
+#else
+#define GRUB_ASM_ATTR
+#endif
+#endif
+
+/* Prototypes for aliases.  */
+#ifndef GRUB_UTIL
+int GRUB_BUILTIN_ATTR EXPORT_FUNC(memcmp) (const void *s1, const void *s2, 
grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memmove) (void *dest, const void *src, 
grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memcpy) (void *dest, const void *src, 
grub_size_t n);
+void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
+
+#ifdef __APPLE__
+void GRUB_BUILTIN_ATTR EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
+#endif
+
+#endif
+
+int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
+int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
+int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
+
+char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
+char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
+int EXPORT_FUNC(grub_strword) (const char *s, const char *w);
+
+/* Copied from gnulib.
+   Written by Bruno Haible <bruno@clisp.org>, 2005. */
+static inline char *
+grub_strstr (const char *haystack, const char *needle)
+{
+  /* Be careful not to look at the entire extent of haystack or needle
+     until needed.  This is useful because of these two cases:
+       - haystack may be very long, and a match of needle found early,
+       - needle may be very long, and not even a short initial segment of
+       needle may be found in haystack.  */
+  if (*needle != '\0')
+    {
+      /* Speed up the following searches of needle by caching its first
+        character.  */
+      char b = *needle++;
+
+      for (;; haystack++)
+       {
+         if (*haystack == '\0')
+           /* No match.  */
+           return 0;
+         if (*haystack == b)
+           /* The first character matches.  */
+           {
+             const char *rhaystack = haystack + 1;
+             const char *rneedle = needle;
+
+             for (;; rhaystack++, rneedle++)
+               {
+                 if (*rneedle == '\0')
+                   /* Found a match.  */
+                   return (char *) haystack;
+                 if (*rhaystack == '\0')
+                   /* No match.  */
+                   return 0;
+                 if (*rhaystack != *rneedle)
+                   /* Nothing in this round.  */
+                   break;
+               }
+           }
+       }
+    }
+  else
+    return (char *) haystack;
+}
+
+int EXPORT_FUNC(grub_isspace) (int c);
+
+static inline int
+grub_isprint (int c)
+{
+  return (c >= ' ' && c <= '~');
+}
+
+static inline int
+grub_iscntrl (int c)
+{
+  return (c >= 0x00 && c <= 0x1F) || c == 0x7F;
+}
+
+static inline int
+grub_isalpha (int c)
+{
+  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+static inline int
+grub_islower (int c)
+{
+  return (c >= 'a' && c <= 'z');
+}
+
+static inline int
+grub_isupper (int c)
+{
+  return (c >= 'A' && c <= 'Z');
+}
+
+static inline int
+grub_isgraph (int c)
+{
+  return (c >= '!' && c <= '~');
+}
+
+static inline int
+grub_isdigit (int c)
+{
+  return (c >= '0' && c <= '9');
+}
+
+static inline int
+grub_isxdigit (int c)
+{
+  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 
'F');
+}
+
+static inline int
+grub_isalnum (int c)
+{
+  return grub_isalpha (c) || grub_isdigit (c);
+}
+
+static inline int
+grub_tolower (int c)
+{
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 'a';
+
+  return c;
+}
+
+static inline int
+grub_toupper (int c)
+{
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 'A';
+
+  return c;
+}
+
+static inline int
+grub_strcasecmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (grub_tolower ((grub_uint8_t) *s1)
+         != grub_tolower ((grub_uint8_t) *s2))
+       break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower ((grub_uint8_t) *s1)
+    - (int) grub_tolower ((grub_uint8_t) *s2);
+}
+
+static inline int
+grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+
+  while (*s1 && *s2 && --n)
+    {
+      if (grub_tolower (*s1) != grub_tolower (*s2))
+       break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower ((grub_uint8_t) *s1)
+    - (int) grub_tolower ((grub_uint8_t) *s2);
+}
+
+unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int 
base);
+unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, 
int base);
+
+static inline long
+grub_strtol (const char *str, char **end, int base)
+{
+  int negative = 0;
+  unsigned long long magnitude;
+
+  while (*str && grub_isspace (*str))
+    str++;
+
+  if (*str == '-')
+    {
+      negative = 1;
+      str++;
+    }
+
+  magnitude = grub_strtoull (str, end, base);
+  if (negative)
+    {
+      if (magnitude > (unsigned long) GRUB_LONG_MAX + 1)
+        {
+          grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+          return GRUB_LONG_MIN;
+        }
+      return -((long) magnitude);
+    }
+  else
+    {
+      if (magnitude > GRUB_LONG_MAX)
+        {
+          grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+          return GRUB_LONG_MAX;
+        }
+      return (long) magnitude;
+    }
+}
+
+char *EXPORT_FUNC(grub_strdup) (const char *s) WARN_UNUSED_RESULT;
+char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n) 
WARN_UNUSED_RESULT;
+void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
+grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) WARN_UNUSED_RESULT;
+int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format 
(GNU_PRINTF, 1, 2)));
+int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format 
(GNU_PRINTF, 1, 2)));
+
+/* Replace all `ch' characters of `input' with `with' and copy the
+   result into `output'; return EOS address of `output'. */
+static inline char *
+grub_strchrsub (char *output, const char *input, char ch, const char *with)
+{
+  while (*input)
+    {
+      if (*input == ch)
+       {
+         grub_strcpy (output, with);
+         output += grub_strlen (with);
+         input++;
+         continue;
+       }
+      *output++ = *input++;
+    }
+  *output = '\0';
+  return output;
+}
+
+extern void (*EXPORT_VAR (grub_xputs)) (const char *str);
+
+static inline int
+grub_puts (const char *s)
+{
+  const char nl[2] = "\n";
+  grub_xputs (s);
+  grub_xputs (nl);
+
+  return 1;    /* Cannot fail.  */
+}
+
+int EXPORT_FUNC(grub_puts_) (const char *s);
+void EXPORT_FUNC(grub_real_dprintf) (const char *file,
+                                     const int line,
+                                     const char *condition,
+                                     const char *fmt, ...) __attribute__ 
((format (GNU_PRINTF, 4, 5)));
+int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args);
+int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...)
+     __attribute__ ((format (GNU_PRINTF, 3, 4)));
+int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
+                                va_list args);
+char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
+     __attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT;
+char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) 
WARN_UNUSED_RESULT;
+void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
+grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
+                                         grub_uint64_t d,
+                                         grub_uint64_t *r);
+
+#if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
+void EXPORT_FUNC (__register_frame_info) (void);
+void EXPORT_FUNC (__deregister_frame_info) (void);
+void EXPORT_FUNC (___chkstk_ms) (void);
+void EXPORT_FUNC (__chkstk_ms) (void);
+#endif
+
+/* Inline functions.  */
+
+static inline char *
+grub_memchr (const void *p, int c, grub_size_t len)
+{
+  const char *s = (const char *) p;
+  const char *e = s + len;
+
+  for (; s < e; s++)
+    if (*s == c)
+      return (char *) s;
+
+  return 0;
+}
+
+
+static inline unsigned int
+grub_abs (int x)
+{
+  if (x < 0)
+    return (unsigned int) (-x);
+  else
+    return (unsigned int) x;
+}
+
+/* Rounded-up division */
+static inline unsigned int
+grub_div_roundup (unsigned int x, unsigned int y)
+{
+  return (x + y - 1) / y;
+}
+
+/* Reboot the machine.  */
+#if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS)
+void EXPORT_FUNC(grub_reboot) (void) __attribute__ ((noreturn));
+#else
+void grub_reboot (void) __attribute__ ((noreturn));
+#endif
+
+#if defined (__clang__) && !defined (GRUB_UTIL)
+void __attribute__ ((noreturn)) EXPORT_FUNC (abort) (void);
+#endif
+
+#ifdef GRUB_MACHINE_PCBIOS
+/* Halt the system, using APM if possible. If NO_APM is true, don't
+ * use APM even if it is available.  */
+void grub_halt (int no_apm) __attribute__ ((noreturn));
+#elif defined (__mips__) && !defined (GRUB_MACHINE_EMU)
+void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn));
+#else
+void grub_halt (void) __attribute__ ((noreturn));
+#endif
+
+#ifdef GRUB_MACHINE_EMU
+/* Flag to check if module loading is available.  */
+extern const int EXPORT_VAR(grub_no_modules);
+#else
+#define grub_no_modules 0
+#endif
+
+static inline void
+grub_error_save (struct grub_error_saved *save)
+{
+  grub_memcpy (save->errmsg, grub_errmsg, sizeof (save->errmsg));
+  save->grub_errno = grub_errno;
+  grub_errno = GRUB_ERR_NONE;
+}
+
+static inline void
+grub_error_load (const struct grub_error_saved *save)
+{
+  grub_memcpy (grub_errmsg, save->errmsg, sizeof (grub_errmsg));
+  grub_errno = save->grub_errno;
+}
+
+#ifndef GRUB_UTIL
+
+#if defined (__arm__)
+
+grub_uint32_t
+EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
+
+grub_uint32_t
+EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
+
+#endif
+
+#if defined (__sparc__) || defined (__powerpc__)
+unsigned
+EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
+#define NEED_CTZDI2 1
+#endif
+
+#if defined (__mips__) || defined (__arm__)
+unsigned
+EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
+#define NEED_CTZSI2 1
+#endif
+
+#ifdef __arm__
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
+grub_uint32_t
+EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
+
+/* Needed for allowing modules to be compiled as thumb.  */
+grub_uint64_t
+EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
+grub_uint64_t
+EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
+
+#endif
+
+#if defined (__ia64__)
+
+grub_uint64_t
+EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
+
+grub_uint64_t
+EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
+
+#endif
+
+#endif /* GRUB_UTIL */
+
+
+#if BOOT_TIME_STATS
+struct grub_boot_time
+{
+  struct grub_boot_time *next;
+  grub_uint64_t tp;
+  const char *file;
+  int line;
+  char *msg;
+};
+
+extern struct grub_boot_time *EXPORT_VAR(grub_boot_time_head);
+
+void EXPORT_FUNC(grub_real_boot_time) (const char *file,
+                                      const int line,
+                                      const char *fmt, ...) __attribute__ 
((format (GNU_PRINTF, 3, 4)));
+#define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, 
__VA_ARGS__)
+#else
+#define grub_boot_time(...)
+#endif
+
+#define grub_max(a, b) (((a) > (b)) ? (a) : (b))
+#define grub_min(a, b) (((a) < (b)) ? (a) : (b))
+
+#endif /* ! GRUB_MISC_HEADER */
diff --git a/i386/grub/mm.h b/i386/grub/mm.h
new file mode 100644
index 0000000..28e2e53
--- /dev/null
+++ b/i386/grub/mm.h
@@ -0,0 +1,77 @@
+/* mm.h - prototypes and declarations for memory manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MM_H
+#define GRUB_MM_H      1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <config.h>
+
+#ifndef NULL
+# define NULL  ((void *) 0)
+#endif
+
+void grub_mm_init_region (void *addr, grub_size_t size);
+void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
+void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
+void EXPORT_FUNC(grub_free) (void *ptr);
+void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size);
+#ifndef GRUB_MACHINE_EMU
+void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
+#endif
+
+void grub_mm_check_real (const char *file, int line);
+#define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);
+
+/* For debugging.  */
+#if defined(MM_DEBUG) && !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
+/* Set this variable to 1 when you want to trace all memory function calls.  */
+extern int EXPORT_VAR(grub_mm_debug);
+
+void grub_mm_dump_free (void);
+void grub_mm_dump (unsigned lineno);
+
+#define grub_malloc(size)      \
+  grub_debug_malloc (GRUB_FILE, __LINE__, size)
+
+#define grub_zalloc(size)      \
+  grub_debug_zalloc (GRUB_FILE, __LINE__, size)
+
+#define grub_realloc(ptr,size) \
+  grub_debug_realloc (GRUB_FILE, __LINE__, ptr, size)
+
+#define grub_memalign(align,size)      \
+  grub_debug_memalign (GRUB_FILE, __LINE__, align, size)
+
+#define grub_free(ptr) \
+  grub_debug_free (GRUB_FILE, __LINE__, ptr)
+
+void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
+                                     grub_size_t size);
+void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
+                                      grub_size_t size);
+void EXPORT_FUNC(grub_debug_free) (const char *file, int line, void *ptr);
+void *EXPORT_FUNC(grub_debug_realloc) (const char *file, int line, void *ptr,
+                                      grub_size_t size);
+void *EXPORT_FUNC(grub_debug_memalign) (const char *file, int line,
+                                       grub_size_t align, grub_size_t size);
+#endif /* MM_DEBUG && ! GRUB_UTIL */
+
+#endif /* ! GRUB_MM_H */
diff --git a/i386/grub/symbol.h b/i386/grub/symbol.h
new file mode 100644
index 0000000..ed19f70
--- /dev/null
+++ b/i386/grub/symbol.h
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2006,2007,2008,2009  Free Software 
Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_SYMBOL_HEADER
+#define GRUB_SYMBOL_HEADER     1
+
+#include <config.h>
+
+/* Apple assembler requires local labels to start with a capital L */
+#define LOCAL(sym)     L_ ## sym
+
+/* Add an underscore to a C symbol in assembler code if needed. */
+#ifndef GRUB_UTIL
+
+#ifdef __APPLE__
+#define MACRO_DOLLAR(x) $$ ## x
+#else
+#define MACRO_DOLLAR(x) $ ## x
+#endif
+
+#if HAVE_ASM_USCORE
+#ifdef ASM_FILE
+# define EXT_C(sym)    _ ## sym
+#else
+# define EXT_C(sym)    "_" sym
+#endif
+#else
+# define EXT_C(sym)    sym
+#endif
+
+#ifdef __arm__
+#define END .end
+#endif
+
+#if defined (__APPLE__)
+#define FUNCTION(x)    .globl EXT_C(x) ; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; EXT_C(x):
+#elif defined (__CYGWIN__) || defined (__MINGW32__)
+/* .type not supported for non-ELF targets.  XXX: Check this in configure? */
+#define FUNCTION(x)    .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 32; 
.endef; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 0; 
.endef; EXT_C(x):
+#elif defined (__arm__)
+#define FUNCTION(x)    .globl EXT_C(x) ; .type EXT_C(x), %function ; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; .type EXT_C(x), %object ; EXT_C(x):
+#else
+#define FUNCTION(x)    .globl EXT_C(x) ; .type EXT_C(x), @function ; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; .type EXT_C(x), @object ; EXT_C(x):
+#endif
+#endif
+
+/* Mark an exported symbol.  */
+#ifndef GRUB_SYMBOL_GENERATOR
+# define EXPORT_FUNC(x)        x
+# define EXPORT_VAR(x) x
+#endif /* ! GRUB_SYMBOL_GENERATOR */
+
+#endif /* ! GRUB_SYMBOL_HEADER */
diff --git a/i386/grub/time.h b/i386/grub/time.h
new file mode 100644
index 0000000..64ac99a
--- /dev/null
+++ b/i386/grub/time.h
@@ -0,0 +1,46 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007, 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_TIME_HEADER
+#define KERNEL_TIME_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#ifndef GRUB_MACHINE_EMU
+#include <grub/cpu/time.h>
+#else
+static inline void
+grub_cpu_idle(void)
+{
+}
+#endif
+
+void EXPORT_FUNC(grub_millisleep) (grub_uint32_t ms);
+grub_uint64_t EXPORT_FUNC(grub_get_time_ms) (void);
+
+grub_uint64_t grub_rtc_get_time_ms (void);
+
+static __inline void
+grub_sleep (grub_uint32_t s)
+{
+  grub_millisleep (1000 * s);
+}
+
+void grub_install_get_time_ms (grub_uint64_t (*get_time_ms_func) (void));
+
+#endif /* ! KERNEL_TIME_HEADER */
diff --git a/i386/grub/types.h b/i386/grub/types.h
new file mode 100644
index 0000000..79f765c
--- /dev/null
+++ b/i386/grub/types.h
@@ -0,0 +1,325 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_HEADER
+#define GRUB_TYPES_HEADER      1
+
+#include <config.h>
+#ifndef GRUB_UTIL
+#include <grub/cpu/types.h>
+#endif
+
+#ifdef __MINGW32__
+#define GRUB_PACKED __attribute__ ((packed,gcc_struct))
+#else
+#define GRUB_PACKED __attribute__ ((packed))
+#endif
+
+#ifdef GRUB_BUILD
+# define GRUB_CPU_SIZEOF_VOID_P        BUILD_SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG  BUILD_SIZEOF_LONG
+# if BUILD_WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#elif defined (GRUB_UTIL)
+# define GRUB_CPU_SIZEOF_VOID_P        SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG  SIZEOF_LONG
+# ifdef WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#else /* ! GRUB_UTIL */
+# define GRUB_CPU_SIZEOF_VOID_P        GRUB_TARGET_SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG  GRUB_TARGET_SIZEOF_LONG
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#endif /* ! GRUB_UTIL */
+
+#if GRUB_CPU_SIZEOF_VOID_P != 4 && GRUB_CPU_SIZEOF_VOID_P != 8
+# error "This architecture is not supported because sizeof(void *) != 4 and 
sizeof(void *) != 8"
+#endif
+
+#if GRUB_CPU_SIZEOF_LONG != 4 && GRUB_CPU_SIZEOF_LONG != 8
+# error "This architecture is not supported because sizeof(long) != 4 and 
sizeof(long) != 8"
+#endif
+
+#if !defined (GRUB_UTIL) && !defined (GRUB_TARGET_WORDSIZE)
+# if GRUB_TARGET_SIZEOF_VOID_P == 4
+#  define GRUB_TARGET_WORDSIZE 32
+# elif GRUB_TARGET_SIZEOF_VOID_P == 8
+#  define GRUB_TARGET_WORDSIZE 64
+# endif
+#endif
+
+/* Define various wide integers.  */
+typedef signed char            grub_int8_t;
+typedef short                  grub_int16_t;
+typedef int                    grub_int32_t;
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef long                   grub_int64_t;
+#else
+typedef long long              grub_int64_t;
+#endif
+
+typedef unsigned char          grub_uint8_t;
+typedef unsigned short         grub_uint16_t;
+typedef unsigned               grub_uint32_t;
+# define PRIxGRUB_UINT32_T     "x"
+# define PRIuGRUB_UINT32_T     "u"
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef unsigned long          grub_uint64_t;
+# define PRIxGRUB_UINT64_T     "lx"
+# define PRIuGRUB_UINT64_T     "lu"
+#else
+typedef unsigned long long     grub_uint64_t;
+# define PRIxGRUB_UINT64_T     "llx"
+# define PRIuGRUB_UINT64_T     "llu"
+#endif
+
+/* Misc types.  */
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef grub_uint64_t  grub_addr_t;
+typedef grub_uint64_t  grub_size_t;
+typedef grub_int64_t   grub_ssize_t;
+
+# define GRUB_SIZE_MAX 18446744073709551615UL
+
+# if GRUB_CPU_SIZEOF_LONG == 8
+#  define PRIxGRUB_SIZE         "lx"
+#  define PRIxGRUB_ADDR         "lx"
+#  define PRIuGRUB_SIZE         "lu"
+#  define PRIdGRUB_SSIZE "ld"
+# else
+#  define PRIxGRUB_SIZE         "llx"
+#  define PRIxGRUB_ADDR         "llx"
+#  define PRIuGRUB_SIZE  "llu"
+#  define PRIdGRUB_SSIZE "lld"
+# endif
+#else
+typedef grub_uint32_t  grub_addr_t;
+typedef grub_uint32_t  grub_size_t;
+typedef grub_int32_t   grub_ssize_t;
+
+# define GRUB_SIZE_MAX 4294967295UL
+
+# define PRIxGRUB_SIZE "x"
+# define PRIxGRUB_ADDR "x"
+# define PRIuGRUB_SIZE "u"
+# define PRIdGRUB_SSIZE        "d"
+#endif
+
+#define GRUB_UCHAR_MAX 0xFF
+#define GRUB_USHRT_MAX 65535
+#define GRUB_SHRT_MAX 0x7fff
+#define GRUB_UINT_MAX 4294967295U
+#define GRUB_INT_MAX 0x7fffffff
+#define GRUB_INT32_MIN (-2147483647 - 1)
+#define GRUB_INT32_MAX 2147483647
+
+#if GRUB_CPU_SIZEOF_LONG == 8
+# define GRUB_ULONG_MAX 18446744073709551615UL
+# define GRUB_LONG_MAX 9223372036854775807L
+# define GRUB_LONG_MIN (-9223372036854775807L - 1)
+#else
+# define GRUB_ULONG_MAX 4294967295UL
+# define GRUB_LONG_MAX 2147483647L
+# define GRUB_LONG_MIN (-2147483647L - 1)
+#endif
+
+typedef grub_uint64_t grub_properly_aligned_t;
+
+#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t 
name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof 
(grub_properly_aligned_t)]
+
+/* The type for representing a file offset.  */
+typedef grub_uint64_t  grub_off_t;
+
+/* The type for representing a disk block address.  */
+typedef grub_uint64_t  grub_disk_addr_t;
+
+/* Byte-orders.  */
+static inline grub_uint16_t grub_swap_bytes16(grub_uint16_t _x)
+{
+   return (grub_uint16_t) ((_x << 8) | (_x >> 8));
+}
+
+#define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 
0xff00) >> 8))
+#define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 
0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24))
+#define grub_swap_bytes64_compile_time(x)      \
+({ \
+   grub_uint64_t _x = (x); \
+   (grub_uint64_t) ((_x << 56) \
+                    | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+
+#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 
3)
+static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
+{
+       return __builtin_bswap32(x);
+}
+
+static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
+{
+       return __builtin_bswap64(x);
+}
+#else                                  /* not gcc 4.3 or newer */
+static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t _x)
+{
+   return ((_x << 24)
+          | ((_x & (grub_uint32_t) 0xFF00UL) << 8)
+          | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8)
+          | (_x >> 24));
+}
+
+static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t _x)
+{
+   return ((_x << 56)
+          | ((_x & (grub_uint64_t) 0xFF00ULL) << 40)
+          | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24)
+          | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8)
+          | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8)
+          | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24)
+          | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40)
+          | (_x >> 56));
+}
+#endif                                 /* not gcc 4.3 or newer */
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+# define grub_cpu_to_le16(x)   grub_swap_bytes16(x)
+# define grub_cpu_to_le32(x)   grub_swap_bytes32(x)
+# define grub_cpu_to_le64(x)   grub_swap_bytes64(x)
+# define grub_le_to_cpu16(x)   grub_swap_bytes16(x)
+# define grub_le_to_cpu32(x)   grub_swap_bytes32(x)
+# define grub_le_to_cpu64(x)   grub_swap_bytes64(x)
+# define grub_cpu_to_be16(x)   ((grub_uint16_t) (x))
+# define grub_cpu_to_be32(x)   ((grub_uint32_t) (x))
+# define grub_cpu_to_be64(x)   ((grub_uint64_t) (x))
+# define grub_be_to_cpu16(x)   ((grub_uint16_t) (x))
+# define grub_be_to_cpu32(x)   ((grub_uint32_t) (x))
+# define grub_be_to_cpu64(x)   ((grub_uint64_t) (x))
+# define grub_cpu_to_be16_compile_time(x)      ((grub_uint16_t) (x))
+# define grub_cpu_to_be32_compile_time(x)      ((grub_uint32_t) (x))
+# define grub_cpu_to_be64_compile_time(x)      ((grub_uint64_t) (x))
+# define grub_be_to_cpu64_compile_time(x)      ((grub_uint64_t) (x))
+# define grub_cpu_to_le32_compile_time(x)      
grub_swap_bytes32_compile_time(x)
+# define grub_cpu_to_le64_compile_time(x)      
grub_swap_bytes64_compile_time(x)
+# define grub_cpu_to_le16_compile_time(x)      
grub_swap_bytes16_compile_time(x)
+#else /* ! WORDS_BIGENDIAN */
+# define grub_cpu_to_le16(x)   ((grub_uint16_t) (x))
+# define grub_cpu_to_le32(x)   ((grub_uint32_t) (x))
+# define grub_cpu_to_le64(x)   ((grub_uint64_t) (x))
+# define grub_le_to_cpu16(x)   ((grub_uint16_t) (x))
+# define grub_le_to_cpu32(x)   ((grub_uint32_t) (x))
+# define grub_le_to_cpu64(x)   ((grub_uint64_t) (x))
+# define grub_cpu_to_be16(x)   grub_swap_bytes16(x)
+# define grub_cpu_to_be32(x)   grub_swap_bytes32(x)
+# define grub_cpu_to_be64(x)   grub_swap_bytes64(x)
+# define grub_be_to_cpu16(x)   grub_swap_bytes16(x)
+# define grub_be_to_cpu32(x)   grub_swap_bytes32(x)
+# define grub_be_to_cpu64(x)   grub_swap_bytes64(x)
+# define grub_cpu_to_be16_compile_time(x)      
grub_swap_bytes16_compile_time(x)
+# define grub_cpu_to_be32_compile_time(x)      
grub_swap_bytes32_compile_time(x)
+# define grub_cpu_to_be64_compile_time(x)      
grub_swap_bytes64_compile_time(x)
+# define grub_be_to_cpu64_compile_time(x)      
grub_swap_bytes64_compile_time(x)
+# define grub_cpu_to_le16_compile_time(x)      ((grub_uint16_t) (x))
+# define grub_cpu_to_le32_compile_time(x)      ((grub_uint32_t) (x))
+# define grub_cpu_to_le64_compile_time(x)      ((grub_uint64_t) (x))
+
+#endif /* ! WORDS_BIGENDIAN */
+
+static inline grub_uint16_t grub_get_unaligned16 (const void *ptr)
+{
+  struct grub_unaligned_uint16_t
+  {
+    grub_uint16_t d;
+  } GRUB_PACKED;
+  const struct grub_unaligned_uint16_t *dd
+    = (const struct grub_unaligned_uint16_t *) ptr;
+  return dd->d;
+}
+
+static inline void grub_set_unaligned16 (void *ptr, grub_uint16_t val)
+{
+  struct grub_unaligned_uint16_t
+  {
+    grub_uint16_t d;
+  } GRUB_PACKED;
+  struct grub_unaligned_uint16_t *dd = (struct grub_unaligned_uint16_t *) ptr;
+  dd->d = val;
+}
+
+static inline grub_uint32_t grub_get_unaligned32 (const void *ptr)
+{
+  struct grub_unaligned_uint32_t
+  {
+    grub_uint32_t d;
+  } GRUB_PACKED;
+  const struct grub_unaligned_uint32_t *dd
+    = (const struct grub_unaligned_uint32_t *) ptr;
+  return dd->d;
+}
+
+static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val)
+{
+  struct grub_unaligned_uint32_t
+  {
+    grub_uint32_t d;
+  } GRUB_PACKED;
+  struct grub_unaligned_uint32_t *dd = (struct grub_unaligned_uint32_t *) ptr;
+  dd->d = val;
+}
+
+struct grub_unaligned_uint64
+{
+  grub_uint64_t val;
+} GRUB_PACKED;
+
+typedef struct grub_unaligned_uint64 grub_unaligned_uint64_t;
+
+static inline grub_uint64_t grub_get_unaligned64 (const void *ptr)
+{
+  const struct grub_unaligned_uint64 *dd
+    = (const struct grub_unaligned_uint64 *) ptr;
+  return dd->val;
+}
+
+static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
+{
+  struct grub_unaligned_uint64_t
+  {
+    grub_uint64_t d;
+  } GRUB_PACKED;
+  struct grub_unaligned_uint64_t *dd = (struct grub_unaligned_uint64_t *) ptr;
+  dd->d = val;
+}
+
+#define GRUB_CHAR_BIT 8
+
+#endif /* ! GRUB_TYPES_HEADER */
diff --git a/i386/i386at/acpi.c b/i386/i386at/acpi.c
new file mode 100644
index 0000000..ec8aeb1
--- /dev/null
+++ b/i386/i386at/acpi.c
@@ -0,0 +1,82 @@
+/* acpi.c - get acpi tables. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/glue.h>
+#include <grub/acpi.h>
+#include <grub/misc.h>
+
+struct grub_acpi_rsdp_v10 *
+grub_machine_acpi_get_rsdpv1 (void)
+{
+  int ebda_len;
+  grub_uint8_t *ebda, *ptr;
+
+  grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
+  ebda = (grub_uint8_t *) phystokv ((* ((grub_uint16_t *) phystokv (0x40e))) 
<< 4);
+  ebda_len = * (grub_uint16_t *) ebda;
+  if (! ebda_len)
+    return 0;
+  for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
+    if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
+       && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
+       && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
+      return (struct grub_acpi_rsdp_v10 *) ptr;
+
+  grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
+  for (ptr = (grub_uint8_t *) phystokv (0xe0000); ptr < (grub_uint8_t *) 
phystokv (0x100000);
+       ptr += 16)
+    if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
+       && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
+       && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
+      return (struct grub_acpi_rsdp_v10 *) ptr;
+  return 0;
+}
+
+struct grub_acpi_rsdp_v20 *
+grub_machine_acpi_get_rsdpv2 (void)
+{
+  int ebda_len;
+  grub_uint8_t *ebda, *ptr;
+
+  grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
+  ebda = (grub_uint8_t *) phystokv ((* ((grub_uint16_t *) phystokv (0x40e))) 
<< 4);
+  ebda_len = * (grub_uint16_t *) ebda;
+  if (! ebda_len)
+    return 0;
+  for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
+    if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
+       && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
+       && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
+       && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
+       && grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
+       == 0)
+      return (struct grub_acpi_rsdp_v20 *) ptr;
+
+  grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
+  for (ptr = (grub_uint8_t *) phystokv (0xe0000); ptr < (grub_uint8_t *) 
phystokv (0x100000);
+       ptr += 16)
+    if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
+       && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
+       && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
+       && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
+       && grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
+       == 0)
+      return (struct grub_acpi_rsdp_v20 *) ptr;
+  return 0;
+}
diff --git a/i386/i386at/acpihalt.c b/i386/i386at/acpihalt.c
new file mode 100644
index 0000000..23df44f
--- /dev/null
+++ b/i386/i386at/acpihalt.c
@@ -0,0 +1,409 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/glue.h>
+
+#ifdef GRUB_DSDT_TEST
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#define grub_dprintf(cond, args...) printf ( args )
+#define grub_printf printf
+typedef uint64_t grub_uint64_t;
+typedef uint32_t grub_uint32_t;
+typedef uint16_t grub_uint16_t;
+typedef uint8_t grub_uint8_t;
+
+#endif
+
+#include <grub/acpi.h>
+#ifndef GRUB_DSDT_TEST
+#include <grub/i18n.h>
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+#ifndef GRUB_DSDT_TEST
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/cpu/io.h>
+#endif
+
+static inline grub_uint32_t
+decode_length (const grub_uint8_t *ptr, int *numlen)
+{
+  int num_bytes, i;
+  grub_uint32_t ret;
+  if (*ptr < 64)
+    {
+      if (numlen)
+       *numlen = 1;
+      return *ptr;
+    }
+  num_bytes = *ptr >> 6;
+  if (numlen)
+    *numlen = num_bytes + 1;
+  ret = *ptr & 0xf;
+  ptr++;
+  for (i = 0; i < num_bytes; i++)
+    {
+      ret |= *ptr << (8 * i + 4);
+      ptr++;
+    }
+  return ret;
+}
+
+static inline grub_uint32_t
+skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end)
+{
+  const grub_uint8_t *ptr0 = ptr;
+  
+  while (ptr < end && (*ptr == '^' || *ptr == '\\'))
+    ptr++;
+  switch (*ptr)
+    {
+    case '.':
+      ptr++;
+      ptr += 8;
+      break;
+    case '/':
+      ptr++;
+      ptr += 1 + (*ptr) * 4;
+      break;
+    case 0:
+      ptr++;
+      break;
+    default:
+      ptr += 4;
+      break;
+    }
+  return ptr - ptr0;
+}
+
+static inline grub_uint32_t
+skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
+{
+  grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
+  switch (*ptr)
+    {
+    case GRUB_ACPI_OPCODE_PACKAGE:
+    case GRUB_ACPI_OPCODE_BUFFER:
+      return 1 + decode_length (ptr + 1, 0);
+    case GRUB_ACPI_OPCODE_ZERO:
+    case GRUB_ACPI_OPCODE_ONES:
+    case GRUB_ACPI_OPCODE_ONE:
+      return 1;
+    case GRUB_ACPI_OPCODE_BYTE_CONST:
+      return 2;
+    case GRUB_ACPI_OPCODE_WORD_CONST:
+      return 3;
+    case GRUB_ACPI_OPCODE_DWORD_CONST:
+      return 5;
+    case GRUB_ACPI_OPCODE_STRING_CONST:
+      {
+       const grub_uint8_t *ptr0 = ptr;
+       for (ptr++; ptr < end && *ptr; ptr++);
+       if (ptr == end)
+         return 0;
+       return ptr - ptr0 + 1;
+      }
+    default:
+      if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
+         || (*ptr >= 'A' && *ptr <= 'Z'))
+       return skip_name_string (ptr, end);
+      grub_printf ("Unknown opcode 0x%x\n", *ptr);
+      return 0;
+    }
+}
+
+static inline grub_uint32_t
+skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
+{
+  const grub_uint8_t *ptr0 = ptr;
+  int add;
+  grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
+  switch (*ptr)
+    {
+    case GRUB_ACPI_EXTOPCODE_MUTEX:
+      ptr++;
+      ptr += skip_name_string (ptr, end);
+      ptr++;
+      break;
+    case GRUB_ACPI_EXTOPCODE_EVENT_OP:
+      ptr++;
+      ptr += skip_name_string (ptr, end);
+      break;
+    case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
+      ptr++;
+      ptr += skip_name_string (ptr, end);
+      ptr++;
+      ptr += add = skip_data_ref_object (ptr, end);
+      if (!add)
+       return 0;
+      ptr += add = skip_data_ref_object (ptr, end);
+      if (!add)
+       return 0;
+      break;
+    case GRUB_ACPI_EXTOPCODE_FIELD_OP:
+    case GRUB_ACPI_EXTOPCODE_DEVICE_OP:
+    case GRUB_ACPI_EXTOPCODE_PROCESSOR_OP:
+    case GRUB_ACPI_EXTOPCODE_POWER_RES_OP:
+    case GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP:
+    case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP:
+    case GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP:
+      ptr++;
+      ptr += decode_length (ptr, 0);
+      break;
+    default:
+      grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
+      return 0;
+    }
+  return ptr - ptr0;
+}
+
+static int
+get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
+               grub_uint8_t *scope, int scope_len)
+{
+  grub_uint8_t *prev = table;
+  
+  if (!ptr)
+    ptr = table + sizeof (struct grub_acpi_table_header);
+  while (ptr < end && prev < ptr)
+    {
+      int add;
+      prev = ptr;
+      grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
+      grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
+      switch (*ptr)
+       {
+       case GRUB_ACPI_OPCODE_EXTOP:
+         ptr++;
+         ptr += add = skip_ext_op (ptr, end);
+         if (!add)
+           return -1;
+         break;
+       case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
+       case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
+         {
+           ptr += 5;
+           ptr += add = skip_data_ref_object (ptr, end);
+           if (!add)
+             return -1;
+           ptr += 4;
+           break;
+         }
+       case GRUB_ACPI_OPCODE_NAME:
+         ptr++;
+         if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) &&
+             (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 
4) == 0))
+           {
+             int ll;
+             grub_uint8_t *ptr2 = ptr;
+             grub_dprintf ("acpi", "S5 found\n");
+             ptr2 += skip_name_string (ptr, end);
+             if (*ptr2 != 0x12)
+               {
+                 grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
+                 return -1;
+               }
+             ptr2++;
+             decode_length (ptr2, &ll);
+             ptr2 += ll;
+             ptr2++;
+             switch (*ptr2)
+               {
+               case GRUB_ACPI_OPCODE_ZERO:
+                 return 0;
+               case GRUB_ACPI_OPCODE_ONE:
+                 return 1;
+               case GRUB_ACPI_OPCODE_BYTE_CONST:
+                 return ptr2[1];
+               default:
+                 grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
+                 return -1;
+               }
+           }
+         ptr += add = skip_name_string (ptr, end);
+         if (!add)
+           return -1;
+         ptr += add = skip_data_ref_object (ptr, end);
+         if (!add)
+           return -1;
+         break;
+       case GRUB_ACPI_OPCODE_SCOPE:
+         {
+           int scope_sleep_type;
+           int ll;
+           grub_uint8_t *name;
+           int name_len;
+
+           ptr++;
+           add = decode_length (ptr, &ll);
+           name = ptr + ll;
+           name_len = skip_name_string (name, ptr + add);
+           if (!name_len)
+             return -1;
+           scope_sleep_type = get_sleep_type (table, name + name_len,
+                                              ptr + add, name, name_len);
+           if (scope_sleep_type != -2)
+             return scope_sleep_type;
+           ptr += add;
+           break;
+         }
+       case GRUB_ACPI_OPCODE_IF:
+       case GRUB_ACPI_OPCODE_METHOD:
+         {
+           ptr++;
+           ptr += decode_length (ptr, 0);
+           break;
+         }
+       default:
+         grub_printf ("Unknown opcode 0x%x\n", *ptr);
+         return -1;      
+       }
+    }
+
+  return -2;
+}
+
+#ifdef GRUB_DSDT_TEST
+int
+main (int argc, char **argv)
+{
+  FILE *f;
+  size_t len;
+  unsigned char *buf;
+  if (argc < 2)
+    printf ("Usage: %s FILE\n", argv[0]);
+  f = grub_util_fopen (argv[1], "rb");
+  if (!f)
+    {
+      printf ("Couldn't open file\n");
+      return 1;
+    }
+  fseek (f, 0, SEEK_END);
+  len = ftell (f);
+  fseek (f, 0, SEEK_SET);
+  buf = malloc (len);
+  if (!buf)
+    {
+      printf (_("error: %s.\n"), _("out of memory"));
+      fclose (f);
+      return 2;
+    }
+  if (fread (buf, 1, len, f) != len)
+    {
+      printf (_("cannot read `%s': %s"), argv[1], strerror (errno));
+      free (buf);
+      fclose (f);
+      return 2;
+    }
+
+  printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0));
+  free (buf);
+  fclose (f);
+  return 0;
+}
+
+#else
+
+void
+grub_acpi_halt (void)
+{
+  struct grub_acpi_rsdp_v20 *rsdp2;
+  struct grub_acpi_rsdp_v10 *rsdp1;
+  struct grub_acpi_table_header *rsdt;
+  grub_uint32_t *entry_ptr;
+  grub_uint32_t port = 0;
+  int sleep_type = -1;
+
+  rsdp2 = grub_acpi_get_rsdpv2 ();
+  if (rsdp2)
+    rsdp1 = &(rsdp2->rsdpv1);
+  else
+    rsdp1 = grub_acpi_get_rsdpv1 ();
+  grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
+  if (!rsdp1)
+    return;
+
+  rsdt = (struct grub_acpi_table_header *)
+    io_map_cached (rsdp1->rsdt_addr, sizeof *rsdt);
+  rsdt = (struct grub_acpi_table_header *)
+    io_map_cached (rsdp1->rsdt_addr, rsdt->length);
+
+  for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
+       entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
+                                     + rsdt->length);
+       entry_ptr++)
+    {
+      if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4),
+                      "FACP", 4) == 0)
+       {
+         struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *)
+           io_map_cached (*entry_ptr, sizeof *fadt);
+
+         struct grub_acpi_table_header *dsdt =
+           (struct grub_acpi_table_header *)
+           io_map_cached (fadt->dsdt_addr, sizeof *dsdt);
+         grub_uint8_t *buf = (grub_uint8_t *)
+           io_map_cached (fadt->dsdt_addr, dsdt->length);
+
+         port = fadt->pm1a;
+
+         grub_dprintf ("acpi", "PM1a port=%x\n", port);
+
+         if (grub_memcmp (dsdt->signature, "DSDT",
+                          sizeof (dsdt->signature)) == 0
+             && sleep_type < 0)
+           sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length,
+                                        NULL, 0);
+       }
+      else
+       if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4), "SSDT", 4) == 0
+           && sleep_type < 0)
+       {
+         struct grub_acpi_table_header *ssdt
+           = (struct grub_acpi_table_header *) (grub_addr_t)
+           io_map_cached (*entry_ptr, sizeof *ssdt);
+         grub_uint8_t *buf = (grub_uint8_t *)
+           io_map_cached (*entry_ptr, ssdt->length);
+
+         grub_dprintf ("acpi", "SSDT = %p\n", ssdt);
+
+         sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0);
+       }
+    }
+
+  grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port);
+  if (port && sleep_type >= 0 && sleep_type < 8)
+    grub_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET),
+              port & 0xffff);
+
+  grub_millisleep (1500);
+
+  /* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI.  */
+  grub_puts_ (N_("ACPI shutdown failed"));
+}
+#endif
diff --git a/i386/i386at/acpihalt.h b/i386/i386at/acpihalt.h
new file mode 100644
index 0000000..a4fdb07
--- /dev/null
+++ b/i386/i386at/acpihalt.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Free Software Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ACPIHALT_H_
+#define _ACPIHALT_H_
+
+void grub_acpi_halt (void);
+
+#endif /* _ACPIHALT_H_ */
diff --git a/i386/i386at/grub_glue.c b/i386/i386at/grub_glue.c
new file mode 100644
index 0000000..68a4cb1
--- /dev/null
+++ b/i386/i386at/grub_glue.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014 Free Software Foundation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <kern/printf.h>
+#include <stdarg.h>
+#include <i386/vm_param.h>
+
+#include <grub/glue.h>
+#include <grub/acpi.h>
+
+#define GRUB_DEBUG 0
+
+void
+grub_real_dprintf (const char *file, const int line, const char *condition,
+                  const char *fmt, ...)
+{
+#if GRUB_DEBUG
+  va_list      listp;
+  va_start(listp, fmt);
+  vprintf (fmt, listp);
+  va_end(listp);
+#endif
+}
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+  /* Do nothing.  */
+}
+
+struct grub_acpi_rsdp_v20 *
+grub_acpi_get_rsdpv2 (void)
+{
+  return grub_machine_acpi_get_rsdpv2 ();
+}
+
+struct grub_acpi_rsdp_v10 *
+grub_acpi_get_rsdpv1 (void)
+{
+  return grub_machine_acpi_get_rsdpv1 ();
+}
+
+/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
+grub_uint8_t
+grub_byte_checksum (void *base, grub_size_t size)
+{
+  grub_uint8_t *ptr;
+  grub_uint8_t ret = 0;
+  for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
+       ptr++)
+    ret += *ptr;
+  return ret;
+}
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index 95752fa..6093a66 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -69,6 +69,7 @@
 #include <i386at/kd.h>
 #include <i386at/rtc.h>
 #include <i386at/model_dep.h>
+#include <i386at/acpihalt.h>
 #ifdef MACH_XEN
 #include <xen/console.h>
 #include <xen/store.h>
@@ -231,6 +232,7 @@ void halt_all_cpus(boolean_t reboot)
 #ifdef MACH_HYP
            hyp_halt();
 #endif /* MACH_HYP */
+           grub_acpi_halt();
            printf("In tight loop: hit ctl-alt-del to reboot\n");
            (void) spl0();
        }
-- 
1.9.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]