From 1f2d29244a736b9cda28f83966947450bb2e5c9a Mon Sep 17 00:00:00 2001 From: okuji Date: Thu, 19 Oct 2000 21:10:42 +0000 Subject: [PATCH] add apm support. --- ChangeLog | 22 ++++++++ THANKS | 1 + docs/multiboot.texi | 36 +++++++++++-- grub/asmstub.c | 8 +++ stage2/Makefile.am | 2 +- stage2/Makefile.in | 2 +- stage2/apm.S | 127 ++++++++++++++++++++++++++++++++++++++++++++ stage2/asm.S | 13 ++++- stage2/common.c | 8 +++ stage2/mb_info.h | 20 +++++++ stage2/shared.h | 4 ++ 11 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 stage2/apm.S diff --git a/ChangeLog b/ChangeLog index 1238333f5..61b3cedc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2000-10-20 OKUJI Yoshinori + + APM BIOS table support is added, based on a patch by Matt Yourst + . + + * docs/multiboot.texi (Boot information format): Added the + definition of APM table format. + + * stage2/mb_info.h (apm_info): New structure. + (multiboot_info): Added a new element, apm_table. + (MB_INFO_APM_TABLE): New macro. + * stage2/asm.S (apm_bios_info): New variable. + Include "apm.S". + * stage2/apm.S: New file. + * stage2/common.c (init_bios_info) [!STAGE1_5]: Added APM BIOS + table support. + * stage2/shared.h (apm_bios_info): Declared. + (get_apm_info): Likewise. + * stage2/Makefile.am (EXTRA_DIST): Added apm.S. + * grub/asmstub.c (apm_bios_info): New variable. + (get_apm_info): New function. + 2000-10-19 OKUJI Yoshinori Segregate functions which are copyrighted differently. diff --git a/THANKS b/THANKS index a593f4995..5b0a58467 100644 --- a/THANKS +++ b/THANKS @@ -36,6 +36,7 @@ Klaus Reichl Kunihiro Ishiguro M. Meiarashi Mark Lundeberg +Matt Yourst Matthias Kretschmer Michael Hohmuth Mike Meyer diff --git a/docs/multiboot.texi b/docs/multiboot.texi index f0b0d3569..90fa85177 100644 --- a/docs/multiboot.texi +++ b/docs/multiboot.texi @@ -574,7 +574,7 @@ follows: +-------------------+ 64 | boot_loader_name | (present if flags[9] is set) +-------------------+ -68 - ?? | apm_table | (present if flags[10] is set) +68 | apm_table | (present if flags[10] is set) +-------------------+ ?? - ?? | graphics_table | (present if flags[11] is set) +-------------------+ @@ -823,11 +823,41 @@ returned by the @dfn{GET CONFIGURATION} @sc{bios} call. If the @sc{bios} call fails, then the size of the table must be @emph{zero}. If bit 9 in the @samp{flags} is set, the @samp{boot_loader_name} field -is valid, and contains the physical address of the name of the boot +is valid, and contains the physical address of the name of a boot loader booting the kernel. The name is a normal C-style zero-terminated string. -@c I haven't defined the apm_table field yet. - okuji +If bit 10 in the @samp{flags} is set, the @samp{apm_table} field is +valid, and contains the physical address of an @sc{apm} table defined as +below: + +@example +@group + +----------------------+ +0 | version | +2 | cseg | +4 | offset | +8 | cseg_16 | +10 | dseg | +12 | flags | +14 | cseg_len | +16 | cseg_16_len | +18 | dseg_len | + +----------------------+ +@end group +@end example + +The fields @samp{version}, @samp{cseg}, @samp{offset}, @samp{cseg_16}, +@samp{dseg}, @samp{flags}, @samp{cseg_len}, @samp{cseg_16_len}, +@samp{dseg_len} indicate the version number, the protected mode 32-bit +code segment, the offset of the entry point, the protected mode 16-bit +code segment, the protected mode 16-bit data segment, the flags, the +length of the protected mode 32-bit code segment, the length of the +protected mode 16-bit code segment, and the length of the protected mode +16-bit data segment, respectively. Only the field @samp{offset} is 4 +bytes, and the others are 2 bytes. See +@uref{http://www.microsoft.com/hwdev/busbios/amp_12.htm, Advanced Power +Management (APM) BIOS Interface Specification}, for more information. If bit 11 in the @samp{flags} is set, video mode information is available in the mode table. This should only be done if the kernel has diff --git a/grub/asmstub.c b/grub/asmstub.c index a3821ce14..04efd8966 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -72,6 +72,7 @@ char version_string[] = VERSION; char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ unsigned long linux_text_len = 0; unsigned short io_map[IO_MAP_SIZE]; +struct apm_info apm_bios_info; /* Emulation requirements. */ char *grub_scratch_mem = 0; @@ -438,6 +439,13 @@ get_rom_config_table (void) return 0; } +/* Get APM BIOS information. */ +void +get_apm_info (void) +{ + /* Nothing to do in the simulator. */ +} + /* low-level timing info */ int getrtsecs (void) diff --git a/stage2/Makefile.am b/stage2/Makefile.am index f3e927a1e..e34a396f0 100644 --- a/stage2/Makefile.am +++ b/stage2/Makefile.am @@ -7,7 +7,7 @@ noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ fat.h filesys.h freebsd.h fs.h i386-elf.h imgact_aout.h \ mb_header.h mb_info.h md5.h pc_slice.h serial.h shared.h \ smp-imps.h nbi.h -EXTRA_DIST = setjmp.S $(noinst_SCRIPTS) +EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) # For . INCLUDES = -I$(top_srcdir)/stage1 diff --git a/stage2/Makefile.in b/stage2/Makefile.in index ec075a204..f7bfa1b01 100644 --- a/stage2/Makefile.in +++ b/stage2/Makefile.in @@ -96,7 +96,7 @@ noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ mb_header.h mb_info.h md5.h pc_slice.h serial.h shared.h \ smp-imps.h nbi.h -EXTRA_DIST = setjmp.S $(noinst_SCRIPTS) +EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) # For . INCLUDES = -I$(top_srcdir)/stage1 diff --git a/stage2/apm.S b/stage2/apm.S new file mode 100644 index 000000000..1be313b87 --- /dev/null +++ b/stage2/apm.S @@ -0,0 +1,127 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is stolen from arch/i386/boot/setup.S in Linux 2.2.17 */ +/* +! setup.S Copyright (C) 1991, 1992 Linus Torvalds +*/ + +ENTRY(get_apm_info) + pushl %ebp + pushl %ebx + pushl %edi + pushl %esi + + call EXT_C(prot_to_real) + .code16 + + /* APM BIOS installation check */ + movw $0x5300, %ax + xorw %bx, %bx + int $0x15 + /* error -> no APM BIOS */ + jc done_apm_bios + + /* check for "PM" signature */ + cmpw $0x504d, %bx + /* no signature -> no APM BIOS */ + jne done_apm_bios + + /* Is 32 bit supported? */ + andw $0x0002, %cx + /* no ... */ + je done_apm_bios + + /* Disconnect first just in case */ + movw $0x5304, %ax + xorw %bx, %bx + /* ignore return code */ + int $0x15 + + /* 32 bit connect */ + movw $0x5303, %ax + xorl %ebx, %ebx + /* paranoia */ + xorw %cx, %cx + xorw %dx, %dx + xorl %esi, %esi + xorw %di, %di + int $0x15 + /* error */ + jc no_32_apm_bios + + /* BIOS code segment */ + movw %ax, ABS(EXT_C(apm_bios_info)) + 2 + /* BIOS entry point offset */ + movl %ebx, ABS(EXT_C(apm_bios_info)) + 4 + /* BIOS 16 bit code segment */ + movw %cx, ABS(EXT_C(apm_bios_info)) + 8 + /* BIOS data segment */ + movw %dx, ABS(EXT_C(apm_bios_info)) + 10 + /* BIOS code segment length */ + movl %esi, ABS(EXT_C(apm_bios_info)) + 14 + /* BIOS data segment length */ + movw %di, ABS(EXT_C(apm_bios_info)) + 18 + + /* + * Redo the installation check as the 32 bit connect + * modifies the flags returned on some BIOSs + */ + + /* APM BIOS installation check */ + movw $0x5300, %ax + xorw %bx, %bx + /* paranoia */ + xorw %cx, %cx + int $0x15 + /* error -> should not happen, tidy up */ + jc apm_disconnect + + /* check for "PM" signature */ + cmpw $0x504d, %bx + /* no signature -> should not happen, tidy up */ + jne apm_disconnect + + /* record the APM BIOS version */ + movw %ax, ABS(EXT_C(apm_bios_info)) + /* and flags */ + movw %cx, ABS(EXT_C(apm_bios_info)) + 12 + jmp done_apm_bios + +apm_disconnect: + /* Disconnect */ + movw $0x5304, %ax + xorw %bx, %bx + /* ignore return code */ + int $0x15 + jmp done_apm_bios + +no_32_apm_bios: + /* remove 32 bit support bit */ + andw $0xfffd, ABS(EXT_C(apm_bios_info)) + 12 + +done_apm_bios: + DATA32 call EXT_C(prot_to_real) + .code32 + + popl %esi + popl %edi + popl %ebx + popl %ebp + ret diff --git a/stage2/asm.S b/stage2/asm.S index 65cb01e1a..4b2cd5066 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -1324,7 +1324,8 @@ probe_values: /* Source files are splitted, as they have different copyrights. */ #include "setjmp.S" - +#include "apm.S" + /* * console_putchar(c) * @@ -2106,6 +2107,16 @@ offset: segment: .word 0 +VARIABLE(apm_bios_info) + .word 0 /* version */ + .word 0 /* cseg */ + .long 0 /* offset */ + .word 0 /* cseg_16 */ + .word 0 /* dseg_16 */ + .word 0 /* cseg_len */ + .word 0 /* cseg_16_len */ + .word 0 /* dseg_16_len */ + /* * This is the Global Descriptor Table * diff --git a/stage2/common.c b/stage2/common.c index b56bc1faa..0234df649 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -307,6 +307,11 @@ init_bios_info (void) /* Set the boot loader name. */ mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION; + + /* Get the APM BIOS table. */ + get_apm_info (); + if (apm_bios_info.version) + mbi.apm_table = (unsigned long) &apm_bios_info; /* * Initialize other Multiboot Info flags. @@ -315,6 +320,9 @@ init_bios_info (void) mbi.flags = (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV | MB_INFO_DRIVE_INFO | MB_INFO_CONFIG_TABLE | MB_INFO_BOOT_LOADER_NAME); + + if (apm_bios_info.version) + mbi.flags |= MB_INFO_APM_TABLE; #endif /* STAGE1_5 */ diff --git a/stage2/mb_info.h b/stage2/mb_info.h index af2442d51..6f023e07d 100644 --- a/stage2/mb_info.h +++ b/stage2/mb_info.h @@ -83,6 +83,20 @@ struct drive_info #define MB_DI_LBA_MODE 1 +/* APM BIOS info. */ +struct apm_info +{ + unsigned short version; + unsigned short cseg; + unsigned long offset; + unsigned short cseg_16; + unsigned short dseg_16; + unsigned short cseg_len; + unsigned short cseg_16_len; + unsigned short dseg_16_len; +}; + + /* * MultiBoot Info description * @@ -146,6 +160,9 @@ struct multiboot_info /* Boot Loader Name */ unsigned long boot_loader_name; + + /* APM table */ + unsigned long apm_table; }; /* @@ -180,6 +197,9 @@ struct multiboot_info /* Is there a boot loader name? */ #define MB_INFO_BOOT_LOADER_NAME 0x200 +/* Is there a APM table? */ +#define MB_INFO_APM_TABLE 0x400 + /* * The following value must be present in the EAX register. */ diff --git a/stage2/shared.h b/stage2/shared.h index 8e39fb27f..f7295e920 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -466,6 +466,7 @@ typedef enum extern unsigned long install_partition; extern unsigned long boot_drive; extern unsigned long install_second_sector; +extern struct apm_info apm_bios_info; extern unsigned long boot_part_addr; extern unsigned long boot_part_offset; extern int saved_entryno; @@ -658,6 +659,9 @@ int get_mmap_entry (struct mmar_desc *desc, int cont); if fails. */ unsigned long get_rom_config_table (void); +/* Get APM BIOS information. */ +void get_apm_info (void); + /* Return the data area immediately following our code. */ int get_code_end (void);