From 11236082eacb8104aba99a8e1d332e26bcd87976 Mon Sep 17 00:00:00 2001 From: okuji Date: Sun, 15 Oct 2000 21:18:14 +0000 Subject: [PATCH] change the format of drive info in the Multiboot Specification, implement some of the new features. --- ChangeLog | 28 +++++++ docs/grub-install.8 | 5 +- docs/multiboot.texi | 44 +++++------ grub/asmstub.c | 14 ++++ stage2/asm.S | 44 +++++++++++ stage2/common.c | 52 ++++++++++++- stage2/mb_info.h | 173 ++++++++++++++++++++++++++++---------------- stage2/shared.h | 4 + stage2/stage2.c | 2 +- 9 files changed, 277 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ae7df642..1a6637f29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2000-10-16 OKUJI Yoshinori + + Some of the new Multiboot features are supported. APM support + and VESA support are not strictly defined or implemented yet. + + * docs/multiboot.texi (Top): Increase the version number. + (Boot information format): Changed the drive information format, + because it was not straightforward. + + * grub/asmstub.c (io_map): New variable. + (track_int13): New function. + (get_rom_config_table): Likewise. + * stage2/stage2.c (cmain): Set CONFIG_ENTRIES to MBI.DRIVES_ADDR + + MBI.DRIVES.LENGTH instead of MBI.MMAP_ADDR + MBI.MMAP_LENGTH. + * stage2/common.c (init_bios_info) [!STAGE1_5]: Added support + for drive info, ROM config table, and boot loader name features + of the Multiboot Specification. + * stage2/mb_info.h (drive_info): New structure. + (MB_DI_CHS_MODE): New macro. + (MB_DI_LBA_MODE): Likewise. + (multiboot_info): Added drives_length, drives_addr, + config_table, and boot_loader_name. + (MB_INFO_DRIVE_INFO): New macro. + (MB_INFO_CONFIG_TABLE): Likewise. + (MB_INFO_BOOT_LOADER_NAME): Likewise. + * stage2/asm.S (get_rom_config_table): New function. + * stage2/shared.h (get_rom_config_table): Declared. + 2000-10-16 OKUJI Yoshinori * util/grub-install.in (convert): Check only if the file exists, diff --git a/docs/grub-install.8 b/docs/grub-install.8 index 8a48e60e1..1e4256427 100644 --- a/docs/grub-install.8 +++ b/docs/grub-install.8 @@ -22,8 +22,11 @@ instead of the root directory. use FILE as the grub shell. .TP \fB\-\-force\-lba\fR -Force GRUB to use LBA mode even for a buggy +force GRUB to use LBA mode even for a buggy BIOS. +.TP +\fB\-\-recheck\fR +probe a device map even if it already exists. .PP INSTALL_DEVICE can be a GRUB device name or a system device filename. .PP diff --git a/docs/multiboot.texi b/docs/multiboot.texi index 744110020..f0b0d3569 100644 --- a/docs/multiboot.texi +++ b/docs/multiboot.texi @@ -71,7 +71,7 @@ into another language, under the above conditions for modified versions. @top Multiboot Specification This file documents Multiboot Specification, the proposal for the boot -sequence standard. This edition documents version 0.6.90. +sequence standard. This edition documents version 0.6.91. @end ifnottex @@ -567,7 +567,7 @@ follows: 44 | mmap_length | (present if flags[6] is set) 48 | mmap_addr | (present if flags[6] is set) +-------------------+ -52 | drives_count | (present if flags[7] is set) +52 | drives_length | (present if flags[7] is set) 56 | drives_addr | (present if flags[7] is set) +-------------------+ 60 | config_table | (present if flags[8] is set) @@ -765,29 +765,33 @@ be available for normal use. If bit 7 in the @samp{flags} is set, then the @samp{drives_*} fields are valid, and indicate the address of the physical address of the first -drive structure and the number of drive structures. @samp{drives_addr} -is the address, and @samp{drives_count} is the -number. @samp{drives_count} may be zero. Each drive structure is -formatted as follows: +drive structure and the size of drive structures. @samp{drives_addr} +is the address, and @samp{drives_length} is the total size of drive +structures. Note that @samp{drives_length} may be zero. Each drive +structure is formatted as follows: @example @group +-------------------+ -0 | drive_number | +0 | size | +-------------------+ -1 | drive_mode | +4 | drive_number | +-------------------+ -2 | drive_cylinders | -4 | drive_heads | -5 | drive_sectors | +5 | drive_mode | +-------------------+ -6 | drive_ports | +6 | drive_cylinders | +8 | drive_heads | +9 | drive_sectors | +-------------------+ -10 | reserved (0) | +10 - xx | drive_ports | +-------------------+ @end group @end example +The @samp{size} field specifies the size of this structure. The size +varies, depending on the number of ports. Note that the size may not be +equal to (10 + 2 * the number of ports), because of an alignment. + The @samp{drive_number} field contains the BIOS drive number. The @samp{drive_mode} field represents the access mode used by the boot loader. Currently, the following modes are defined: @@ -807,15 +811,11 @@ cylinders. @samp{drive_heads} contains the number of the heads. @samp{drive_sectors} contains the number of the sectors per track. -The @samp{drive_ports} field contains the physical address of the array -of the I/O ports used for the drive in the @sc{bios} code. The array -consists of zero or more unsigned two-bytes integers, and is terminated -with zero. Note that the array may contain any number of I/O ports that -are not related to the drive actually (such as @sc{dma} controller's -ports). - -The last field @samp{reserved} is reserved for future use, and must be -zero. The size is four bytes. +The @samp{drive_ports} field contains the array of the I/O ports used +for the drive in the @sc{bios} code. The array consists of zero or more +unsigned two-bytes integers, and is terminated with zero. Note that the +array may contain any number of I/O ports that are not related to the +drive actually (such as @sc{dma} controller's ports). If bit 8 in the @samp{flags} is set, then the @samp{config_table} field is valid, and indicates the address of the @sc{rom} configuration table diff --git a/grub/asmstub.c b/grub/asmstub.c index 12cf45e0b..a3821ce14 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -71,6 +71,7 @@ int saved_entryno = 0; 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]; /* Emulation requirements. */ char *grub_scratch_mem = 0; @@ -423,6 +424,19 @@ get_mmap_entry (struct mmar_desc *desc, int cont) return 0; } +/* Track the int13 handler. */ +void +track_int13 (int drive) +{ + /* Nothing to do in the simulator. */ +} + +/* Get the ROM configuration table. */ +unsigned long +get_rom_config_table (void) +{ + return 0; +} /* low-level timing info */ int diff --git a/stage2/asm.S b/stage2/asm.S index 2c0706ee0..d2fa90ac8 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -1596,6 +1596,50 @@ xsmap: pop %ebp ret +/* + * get_rom_config_table() + * + * Get the linear address of a ROM configuration table. Return zero, + * if fails. + */ + +ENTRY(get_rom_config_table) + pushl %ebp + pushl %ebx + + /* zero %ebx for simplicity */ + xorl %ebx, %ebx + + call EXT_C(prot_to_real) + .code16 + + movw $0xc0, %ax + int $0x15 + + jc no_rom_table + testb %ah, %ah + jnz no_rom_table + + movw %es, %dx + jmp found_rom_table + +no_rom_table: + xorw %dx, %dx + xorw %bx, %bx + +found_rom_table: + DATA32 call EXT_C(real_to_prot) + .code32 + + /* compute the linear address */ + movw %dx, %ax + shll $4, %eax + addl %ebx, %eax + + popl %ebx + popl %ebp + ret + /* * gateA20(int linear) * diff --git a/stage2/common.c b/stage2/common.c index 618d34bef..b56bc1faa 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -158,6 +158,7 @@ init_bios_info (void) { #ifndef STAGE1_5 unsigned long cont, memtmp, addr; + int drive; #endif /* @@ -260,11 +261,60 @@ init_bios_info (void) saved_mem_upper = mbi.mem_upper; + /* Get the drive info. */ + /* FIXME: This should be postponed until a Multiboot kernel actually + requires it, because this could slow down the start-up + unreasonably. */ + mbi.drives_length = 0; + mbi.drives_addr = addr; + + /* For now, GRUB doesn't probe floppies, since it is trivial to map + floppy drives to BIOS drives. */ + for (drive = 0x80; drive < 0x88; drive++) + { + struct geometry geom; + struct drive_info *info = (struct drive_info *) addr; + unsigned short *port; + + /* Get the geometry. This ensures that the drive is present. */ + if (get_diskinfo (drive, &geom)) + break; + + /* Clean out the I/O map. */ + grub_memset ((char *) io_map, 0, + IO_MAP_SIZE * sizeof (unsigned short)); + /* Track the int13 handler. */ + track_int13 (drive); + + /* Set the information. */ + info->drive_number = drive; + info->drive_mode = ((geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) + ? MB_DI_LBA_MODE : MB_DI_CHS_MODE); + info->drive_cylinders = geom.cylinders; + info->drive_heads = geom.heads; + info->drive_sectors = geom.sectors; + + addr += sizeof (struct drive_info); + for (port = io_map; *port; port++, addr += sizeof (unsigned short)) + *((unsigned short *) addr) = *port; + + info->size = addr - (unsigned long) info; + mbi.drives_length += info->size; + } + + /* Get the ROM configuration table by INT 15, AH=C0h. */ + mbi.config_table = get_rom_config_table (); + + /* Set the boot loader name. */ + mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION; + /* * Initialize other Multiboot Info flags. */ - mbi.flags = MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV; + mbi.flags = (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV + | MB_INFO_DRIVE_INFO | MB_INFO_CONFIG_TABLE + | MB_INFO_BOOT_LOADER_NAME); #endif /* STAGE1_5 */ diff --git a/stage2/mb_info.h b/stage2/mb_info.h index f01690a75..af2442d51 100644 --- a/stage2/mb_info.h +++ b/stage2/mb_info.h @@ -23,17 +23,17 @@ */ struct mod_list - { - /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ - unsigned long mod_start; - unsigned long mod_end; - - /* Module command line */ - unsigned long cmdline; - - /* padding to take it to 16 bytes (must be zero) */ - unsigned long pad; - }; +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + unsigned long mod_start; + unsigned long mod_end; + + /* Module command line */ + unsigned long cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + unsigned long pad; +}; /* @@ -44,19 +44,45 @@ struct mod_list */ struct AddrRangeDesc - { - unsigned long size; - unsigned long long BaseAddr; - unsigned long long Length; - unsigned long Type; - - /* unspecified optional padding... */ - }; +{ + unsigned long size; + unsigned long long BaseAddr; + unsigned long long Length; + unsigned long Type; + + /* unspecified optional padding... */ +}; /* usable memory "Type", all others are reserved. */ #define MB_ARD_MEMORY 1 +/* Drive Info structure. */ +struct drive_info +{ + /* The size of this structure. */ + unsigned long size; + + /* The BIOS drive number. */ + unsigned char drive_number; + + /* The access mode (see below). */ + unsigned char drive_mode; + + /* The BIOS geometry. */ + unsigned short drive_cylinders; + unsigned char drive_heads; + unsigned char drive_sectors; + + /* The array of I/O ports used for the drive. */ + unsigned short drive_ports[0]; +}; + +/* Drive Mode. */ +#define MB_DI_CHS_MODE 0 +#define MB_DI_LBA_MODE 1 + + /* * MultiBoot Info description * @@ -65,52 +91,62 @@ struct AddrRangeDesc */ struct multiboot_info +{ + /* MultiBoot info version number */ + unsigned long flags; + + /* Available memory from BIOS */ + unsigned long mem_lower; + unsigned long mem_upper; + + /* "root" partition */ + unsigned long boot_device; + + /* Kernel command line */ + unsigned long cmdline; + + /* Boot-Module list */ + unsigned long mods_count; + unsigned long mods_addr; + + union { - /* MultiBoot info version number */ - unsigned long flags; - - /* Available memory from BIOS */ - unsigned long mem_lower; - unsigned long mem_upper; - - /* "root" partition */ - unsigned long boot_device; - - /* Kernel command line */ - unsigned long cmdline; - - /* Boot-Module list */ - unsigned long mods_count; - unsigned long mods_addr; - - union - { - struct - { - /* (a.out) Kernel symbol table info */ - unsigned long tabsize; - unsigned long strsize; - unsigned long addr; - unsigned long pad; - } - a; - - struct - { - /* (ELF) Kernel section header table */ - unsigned long num; - unsigned long size; - unsigned long addr; - unsigned long shndx; - } - e; - } - syms; - - /* Memory Mapping buffer */ - unsigned long mmap_length; - unsigned long mmap_addr; - }; + struct + { + /* (a.out) Kernel symbol table info */ + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long pad; + } + a; + + struct + { + /* (ELF) Kernel section header table */ + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; + } + e; + } + syms; + + /* Memory Mapping buffer */ + unsigned long mmap_length; + unsigned long mmap_addr; + + /* Drive Info buffer */ + unsigned long drives_length; + unsigned long drives_addr; + + /* ROM configuration table */ + unsigned long config_table; + + /* Boot Loader Name */ + unsigned long boot_loader_name; +}; /* * Flags to be set in the 'flags' parameter above @@ -135,6 +171,15 @@ struct multiboot_info /* is there a full memory map? */ #define MB_INFO_MEM_MAP 0x40 +/* Is there drive info? */ +#define MB_INFO_DRIVE_INFO 0x80 + +/* Is there a config table? */ +#define MB_INFO_CONFIG_TABLE 0x100 + +/* Is there a boot loader name? */ +#define MB_INFO_BOOT_LOADER_NAME 0x200 + /* * The following value must be present in the EAX register. */ diff --git a/stage2/shared.h b/stage2/shared.h index 1a5ecb7b1..dcc16c11c 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -643,6 +643,10 @@ int get_eisamemsize (void); map). */ int get_mmap_entry (struct mmar_desc *desc, int cont); +/* Get the linear address of a ROM configuration table. Return zero, + if fails. */ +unsigned long get_rom_config_table (void); + /* Return the data area immediately following our code. */ int get_code_end (void); diff --git a/stage2/stage2.c b/stage2/stage2.c index 543c9d429..c6bbf5a12 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -797,7 +797,7 @@ cmain (void) config_len = 0; menu_len = 0; num_entries = 0; - config_entries = (char *) (mbi.mmap_addr + mbi.mmap_length); + config_entries = (char *) mbi.drives_addr + mbi.drives_length; menu_entries = (char *) MENU_BUF; init_config ();