summaryrefslogtreecommitdiff
path: root/i386/i386at
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-03 01:33:14 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2014-07-06 15:46:04 +0200
commitc031b41b783cc99c0bd5aac7d14c1d6e34520397 (patch)
treed05065f96429bfc620ff39a536cc57b01e082c0e /i386/i386at
parent3bb2b68bc84b9cb11aae7b46eeec3c5eb3363f54 (diff)
i386: use ACPI to power off the machine
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.
Diffstat (limited to 'i386/i386at')
-rw-r--r--i386/i386at/acpi.c82
-rw-r--r--i386/i386at/acpihalt.c409
-rw-r--r--i386/i386at/acpihalt.h23
-rw-r--r--i386/i386at/grub_glue.c67
-rw-r--r--i386/i386at/model_dep.c2
5 files changed, 583 insertions, 0 deletions
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();
}