diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 03505ad5a..584b9754d 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1433,3 +1433,9 @@ module = {
name = testload;
common = commands/testload.c;
};
+
+module = {
+ name = lsapm;
+ common = commands/i386/pc/lsapm.c;
+ enable = i386_pc;
+};
diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c
new file mode 100644
index 000000000..30475d2ec
--- /dev/null
+++ b/grub-core/commands/i386/pc/lsapm.c
@@ -0,0 +1,113 @@
+/*
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+int
+grub_apm_get_info (struct grub_apm_info *info)
+{
+ struct grub_bios_int_registers regs;
+
+ /* detect APM */
+ regs.eax = 0x5300;
+ regs.ebx = 0;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x15, ®s);
+
+ if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+ return 0;
+ info->version = regs.eax & 0xffff;
+ info->flags = regs.ecx & 0xffff;
+
+ /* disconnect APM first */
+ regs.eax = 0x5304;
+ regs.ebx = 0;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x15, ®s);
+
+ /* connect APM */
+ regs.eax = 0x5303;
+ regs.ebx = 0;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x15, ®s);
+
+ if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+ return 0;
+
+ info->cseg = regs.eax & 0xffff;
+ info->offset = regs.ebx;
+ info->cseg_16 = regs.ecx & 0xffff;
+ info->dseg = regs.edx & 0xffff;
+ info->cseg_len = regs.esi >> 16;
+ info->cseg_16_len = regs.esi & 0xffff;
+ info->dseg_len = regs.edi;
+
+ return 1;
+}
+
+static grub_err_t
+grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
+{
+ struct grub_apm_info info;
+ if (!grub_apm_get_info (&info))
+ return grub_error (GRUB_ERR_IO, "no APM found");
+
+ grub_printf ("Vesion %u.%u\n"
+ "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
+ "16-bit CS = 0x%x, len = 0x%x\n"
+ "DS = 0x%x, len = 0x%x\n",
+ info.version >> 8, info.version & 0xff,
+ info.cseg, info.cseg_len, info.offset,
+ info.cseg_16, info.cseg_16_len,
+ info.dseg, info.dseg_len);
+ grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
+ ? "16-bit protected interface supported\n"
+ : "16-bit protected interface unsupported\n");
+ grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
+ ? "32-bit protected interface supported\n"
+ : "32-bit protected interface unsupported\n");
+ grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
+ ? "CPU Idle slows down processor\n"
+ : "CPU Idle doesn't slow down processor\n");
+ grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
+ ? "APM disabled\n" : "APM enabled\n");
+ grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
+ ? "APM disengaged\n" : "APM engaged\n");
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(lsapm)
+{
+ cmd = grub_register_command ("lsapm", grub_cmd_lsapm, 0,
+ N_("Show APM information."));
+}
+
+GRUB_MOD_FINI(lsapm)
+{
+ grub_unregister_command (cmd);
+}
+
+
diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c
index 959d8367d..024d425e8 100644
--- a/grub-core/lib/legacy_parse.c
+++ b/grub-core/lib/legacy_parse.c
@@ -99,7 +99,8 @@ struct legacy_command legacy_commands[] =
"Set the default entry to entry number NUM (if not specified, it is"
" 0, the first entry) or the entry number saved by savedefault."},
/* FIXME: dhcp unsupported. */
- /* FIXME: displayapm unsupported. */
+ {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0,
+ "Display APM BIOS information."},
{"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0,
"Display what GRUB thinks the system address space map of the"
" machine is, including all regions of physical RAM installed."},
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
index bf17863cf..2cce39746 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -20,6 +20,7 @@
#include
#ifdef GRUB_MACHINE_PCBIOS
#include
+#include
#endif
#include
#include
@@ -194,7 +195,8 @@ grub_multiboot_get_mbi_size (void)
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ elf_sec_entsize * elf_sec_num
- + 256 * sizeof (struct multiboot_color);
+ + 256 * sizeof (struct multiboot_color)
+ + ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
}
/* Fill previously allocated Multiboot mmap. */
@@ -356,6 +358,29 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
+#ifdef GRUB_MACHINE_PCBIOS
+ {
+ struct grub_apm_info info;
+ if (grub_apm_get_info (&info))
+ {
+ struct multiboot_apm_info *mbinfo = (void *) ptrorig;
+
+ mbinfo->cseg = info.cseg;
+ mbinfo->offset = info.offset;
+ mbinfo->cseg_16 = info.cseg_16;
+ mbinfo->dseg = info.dseg;
+ mbinfo->flags = info.flags;
+ mbinfo->cseg_len = info.cseg_len;
+ mbinfo->dseg_len = info.dseg_len;
+ mbinfo->cseg_16_len = info.cseg_16_len;
+ mbinfo->version = info.version;
+
+ ptrorig += ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
+ ptrdest += ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
+ }
+ }
+#endif
+
if (modcnt)
{
mbi->flags |= MULTIBOOT_INFO_MODS;
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 8780ec061..d5cb42604 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -21,10 +21,8 @@
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
* - VBE support
- * - symbol table
* - drives table
* - ROM configuration table
- * - APM table
*/
#include
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index f453dcc6a..2e6801252 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -20,6 +20,7 @@
#include
#ifdef GRUB_MACHINE_PCBIOS
#include
+#include
#endif
#include
#include
@@ -279,7 +280,8 @@ grub_multiboot_get_mbi_size (void)
+ elf_sec_entsize * elf_sec_num
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry))
- + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
+ + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1
+ + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1;
}
/* Fill previously allocated Multiboot mmap. */
@@ -515,6 +517,31 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
+#ifdef GRUB_MACHINE_PCBIOS
+ {
+ struct grub_apm_info info;
+ if (grub_apm_get_info (&info))
+ {
+ struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig;
+
+ tag->type = MULTIBOOT_TAG_TYPE_APM;
+ tag->size = sizeof (struct multiboot_tag_apm);
+
+ tag->cseg = info.cseg;
+ tag->offset = info.offset;
+ tag->cseg_16 = info.cseg_16;
+ tag->dseg = info.dseg;
+ tag->flags = info.flags;
+ tag->cseg_len = info.cseg_len;
+ tag->dseg_len = info.dseg_len;
+ tag->cseg_16_len = info.cseg_16_len;
+ tag->version = info.version;
+
+ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
+ }
+ }
+#endif
+
{
unsigned i;
struct module *cur;
diff --git a/include/grub/i386/pc/apm.h b/include/grub/i386/pc/apm.h
new file mode 100644
index 000000000..6d9e8c61d
--- /dev/null
+++ b/include/grub/i386/pc/apm.h
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+
+#ifndef GRUB_APM_MACHINE_HEADER
+#define GRUB_APM_MACHINE_HEADER 1
+
+#include
+
+struct grub_apm_info
+{
+ grub_uint16_t cseg;
+ grub_uint32_t offset;
+ grub_uint16_t cseg_16;
+ grub_uint16_t dseg;
+ grub_uint16_t flags;
+ grub_uint16_t cseg_len;
+ grub_uint16_t cseg_16_len;
+ grub_uint16_t dseg_len;
+ grub_uint16_t version;
+};
+
+enum
+ {
+ GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED = 1,
+ GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED = 2,
+ GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN = 4,
+ GRUB_APM_FLAGS_DISABLED = 8,
+ GRUB_APM_FLAGS_DISENGAGED = 16,
+ };
+
+int grub_apm_get_info (struct grub_apm_info *info);
+
+#endif
diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h
index e1c463925..de23775d0 100644
--- a/include/grub/i386/pc/int.h
+++ b/include/grub/i386/pc/int.h
@@ -20,6 +20,7 @@
#define GRUB_INTERRUPT_MACHINE_HEADER 1
#include
+#include
struct grub_bios_int_registers
{
diff --git a/include/grub/i386/pc/vesa_modes_table.h b/include/grub/i386/pc/vesa_modes_table.h
new file mode 100644
index 000000000..376ca376b
--- /dev/null
+++ b/include/grub/i386/pc/vesa_modes_table.h
@@ -0,0 +1,19 @@
+#ifndef GRUB_VESA_MODE_TABLE_HEADER
+#define GRUB_VESA_MODE_TABLE_HEADER 1
+
+#include
+
+#define GRUB_VESA_MODE_TABLE_START 0x300
+#define GRUB_VESA_MODE_TABLE_END 0x373
+
+struct grub_vesa_mode_table_entry {
+ grub_uint16_t width;
+ grub_uint16_t height;
+ grub_uint8_t depth;
+};
+
+extern struct grub_vesa_mode_table_entry
+grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END
+ - GRUB_VESA_MODE_TABLE_START + 1];
+
+#endif
diff --git a/include/multiboot.h b/include/multiboot.h
index fda863e85..ed71e6b96 100644
--- a/include/multiboot.h
+++ b/include/multiboot.h
@@ -254,6 +254,20 @@ struct multiboot_mod_list
};
typedef struct multiboot_mod_list multiboot_module_t;
+/* APM BIOS info. */
+struct multiboot_apm_info
+{
+ grub_uint16_t version;
+ grub_uint16_t cseg;
+ grub_uint32_t offset;
+ grub_uint16_t cseg_16;
+ grub_uint16_t dseg;
+ grub_uint16_t flags;
+ grub_uint16_t cseg_len;
+ grub_uint16_t cseg_16_len;
+ grub_uint16_t dseg_len;
+};
+
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */