Implement APM

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-15 11:42:18 +02:00
parent e31bb61911
commit 890c9fa5f2
10 changed files with 257 additions and 5 deletions

View file

@ -1433,3 +1433,9 @@ module = {
name = testload; name = testload;
common = commands/testload.c; common = commands/testload.c;
}; };
module = {
name = lsapm;
common = commands/i386/pc/lsapm.c;
enable = i386_pc;
};

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/int.h>
#include <grub/machine/apm.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/i18n.h>
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, &regs);
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, &regs);
/* connect APM */
regs.eax = 0x5303;
regs.ebx = 0;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x15, &regs);
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);
}

View file

@ -99,7 +99,8 @@ struct legacy_command legacy_commands[] =
"Set the default entry to entry number NUM (if not specified, it is" "Set the default entry to entry number NUM (if not specified, it is"
" 0, the first entry) or the entry number saved by savedefault."}, " 0, the first entry) or the entry number saved by savedefault."},
/* FIXME: dhcp unsupported. */ /* 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, {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0,
"Display what GRUB thinks the system address space map of the" "Display what GRUB thinks the system address space map of the"
" machine is, including all regions of physical RAM installed."}, " machine is, including all regions of physical RAM installed."},

View file

@ -20,6 +20,7 @@
#include <grub/memory.h> #include <grub/memory.h>
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h> #include <grub/machine/biosnum.h>
#include <grub/machine/apm.h>
#endif #endif
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/relocator.h> #include <grub/cpu/relocator.h>
@ -194,7 +195,8 @@ grub_multiboot_get_mbi_size (void)
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ elf_sec_entsize * elf_sec_num + 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. */ /* Fill previously allocated Multiboot mmap. */
@ -356,6 +358,29 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4); ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
ptrdest += 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) if (modcnt)
{ {
mbi->flags |= MULTIBOOT_INFO_MODS; mbi->flags |= MULTIBOOT_INFO_MODS;

View file

@ -21,10 +21,8 @@
* FIXME: The following features from the Multiboot specification still * FIXME: The following features from the Multiboot specification still
* need to be implemented: * need to be implemented:
* - VBE support * - VBE support
* - symbol table
* - drives table * - drives table
* - ROM configuration table * - ROM configuration table
* - APM table
*/ */
#include <grub/loader.h> #include <grub/loader.h>

View file

@ -20,6 +20,7 @@
#include <grub/memory.h> #include <grub/memory.h>
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h> #include <grub/machine/biosnum.h>
#include <grub/machine/apm.h>
#endif #endif
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/multiboot.h> #include <grub/cpu/multiboot.h>
@ -279,7 +280,8 @@ grub_multiboot_get_mbi_size (void)
+ elf_sec_entsize * elf_sec_num + elf_sec_entsize * elf_sec_num
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count () + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry)) * 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. */ /* 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); 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; unsigned i;
struct module *cur; struct module *cur;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_APM_MACHINE_HEADER
#define GRUB_APM_MACHINE_HEADER 1
#include <grub/types.h>
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

View file

@ -20,6 +20,7 @@
#define GRUB_INTERRUPT_MACHINE_HEADER 1 #define GRUB_INTERRUPT_MACHINE_HEADER 1
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/types.h>
struct grub_bios_int_registers struct grub_bios_int_registers
{ {

View file

@ -0,0 +1,19 @@
#ifndef GRUB_VESA_MODE_TABLE_HEADER
#define GRUB_VESA_MODE_TABLE_HEADER 1
#include <grub/types.h>
#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

View file

@ -254,6 +254,20 @@ struct multiboot_mod_list
}; };
typedef struct multiboot_mod_list multiboot_module_t; 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 /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */ #endif /* ! MULTIBOOT_HEADER */