diff --git a/ChangeLog b/ChangeLog index 5450e7b57..c7075d681 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2008-02-03 Yoshinori K. Okuji + + Add support for having a grub directory in a different drive. This + is still only the data handling part. + + * kern/i386/pc/startup.S (multiboot_trampoline): Set %dh to 0xFF. + (codestart): Save %dh in GRUB_ROOT_DRIVE. + (grub_root_drive): New variable. + + * kern/i386/pc/init.c (make_install_device): Use GRUB_ROOT_DRIVE + instead of GRUB_BOOT_DRIVE to construct a device name. Set + GRUB_ROOT_DRIVE to GRUB_BOOT_DRIVE if it is 0xFF, otherwise use it + as it was. + + * include/grub/i386/pc/kernel.h (grub_root_drive): New prototype. + + * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_ROOT_DRIVE): New + macro. + (GRUB_BOOT_MACHINE_DRIVE_CHECK): Set to 0x4f. + + * boot/i386/pc/pxeboot.S (_start): Set %dh to 0xFF. For now, this + is bogus, because PXE booting does not specify any drive + correctly. + + * boot/i386/pc/lnxboot.S (reg_edx): Set the second byte to 0xFF. I + am not sure if this is really correct. + + * boot/i386/pc/cdboot.S: Set %dh to 0xFF, because the root drive + is always identical to the boot drive when booting from a CD. + + * boot/i386/pc/boot.S (MOV_MEM_TO_AL): Removed. Not needed any + longer. + (root_drive): New variable. + (real_start): Unconditionally set %dh to ROOT_DRIVE. + (setup_sectors): Push %dx right after popping it, because %dh will + be modified later. + (copy_buffer): Restore %dx. + 2008-02-03 Robert Millan * util/i386/pc/grub-mkrescue.in: Rewrite most of image generation to diff --git a/boot/i386/pc/boot.S b/boot/i386/pc/boot.S index 187b7d2d4..64d40c8fb 100644 --- a/boot/i386/pc/boot.S +++ b/boot/i386/pc/boot.S @@ -32,9 +32,6 @@ /* Print message string */ #define MSG(x) movw $ABS(x), %si; call message - /* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */ -#define MOV_MEM_TO_AL(x) .byte 0xa0; .word x - .file "boot.S" .text @@ -99,6 +96,8 @@ kernel_sector: boot_drive: .byte 0xff /* the disk to load kernel from */ /* 0xff means use the boot drive */ +root_drive: + .byte 0xff after_BPB: @@ -141,7 +140,9 @@ real_start: /* * Check if we have a forced disk reference here */ - MOV_MEM_TO_AL(ABS(boot_drive)) /* movb ABS(boot_drive), %al */ + /* assign root_drive at the same time */ + movw ABS(boot_drive), %ax + movb %ah, %dh cmpb $0xff, %al je 1f movb %al, %dl @@ -303,6 +304,7 @@ setup_sectors: /* restore %dl */ popw %dx + pushw %dx /* head start */ movb %al, %dh @@ -353,6 +355,7 @@ copy_buffer: popw %ds popa + popw %dx /* boot kernel */ jmp *(kernel_address) diff --git a/boot/i386/pc/cdboot.S b/boot/i386/pc/cdboot.S index 61ef84ee9..1709b8c89 100644 --- a/boot/i386/pc/cdboot.S +++ b/boot/i386/pc/cdboot.S @@ -78,6 +78,9 @@ bi_reserved: call read_cdrom + /* Root drive will default to boot drive */ + movb $0xFF, %dh + ljmp $(DATA_ADDR >> 4), $0 /* diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S index 6a4de8dd5..2a913ba9c 100644 --- a/boot/i386/pc/lnxboot.S +++ b/boot/i386/pc/lnxboot.S @@ -115,7 +115,7 @@ gdt_dst2: .long 0, 0, 0, 0 /* More space for the BIOS. */ reg_edx: - .byte 0x80,0,0xFF,0xFF + .byte 0x80, 0xFF, 0xFF, 0xFF data_leng: .long 0 diff --git a/boot/i386/pc/pxeboot.S b/boot/i386/pc/pxeboot.S index 8c547733a..7f2a14396 100644 --- a/boot/i386/pc/pxeboot.S +++ b/boot/i386/pc/pxeboot.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2005,2007 Free Software Foundation, Inc. + * Copyright (C) 2000,2005,2007,2008 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 @@ -25,6 +25,9 @@ /* Let's go */ .globl _start; _start: + /* Root drive will default to boot drive */ + movb $0xFF, %dh + /* Jump to the real world */ ljmp $0, $0x8200 diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h index fcc961b1a..386221414 100644 --- a/include/grub/i386/pc/boot.h +++ b/include/grub/i386/pc/boot.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2002,2005,2006,2007 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2002,2005,2006,2007,2008 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 @@ -34,6 +34,9 @@ /* The offset of BOOT_DRIVE. */ #define GRUB_BOOT_MACHINE_BOOT_DRIVE 0x4c +/* The offset of ROOT_DRIVE. */ +#define GRUB_BOOT_MACHINE_ROOT_DRIVE 0x4d + /* The offset of KERNEL_ADDRESS. */ #define GRUB_BOOT_MACHINE_KERNEL_ADDRESS 0x40 @@ -44,7 +47,7 @@ #define GRUB_BOOT_MACHINE_KERNEL_SEGMENT 0x42 /* The offset of BOOT_DRIVE_CHECK. */ -#define GRUB_BOOT_MACHINE_DRIVE_CHECK 0x4e +#define GRUB_BOOT_MACHINE_DRIVE_CHECK 0x4f /* The offset of a magic number used by Windows NT. */ #define GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC 0x1b8 diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index ca16df788..848dad10d 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2007 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2007,2008 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 @@ -73,6 +73,9 @@ extern char grub_prefix[]; /* The boot BIOS drive number. */ extern grub_int32_t grub_boot_drive; +/* The root BIOS drive number. */ +extern grub_int32_t grub_root_drive; + /* The end address of the kernel. */ extern grub_addr_t grub_end_addr; diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 908e2d791..72374929c 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -72,13 +72,18 @@ make_install_device (void) } else if (grub_install_dos_part != -2) { - if (grub_boot_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START) + /* If the root drive is not set explicitly, assume that it is identical + to the boot drive. */ + if (grub_root_drive == 0xFF) + grub_root_drive = grub_boot_drive; + + if (grub_root_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START) grub_sprintf (dev, "(cd%u", - grub_boot_drive - GRUB_BIOSDISK_MACHINE_CDROM_START); + grub_root_drive - GRUB_BIOSDISK_MACHINE_CDROM_START); else grub_sprintf (dev, "(%cd%u", - (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f); + (grub_root_drive & 0x80) ? 'h' : 'f', + grub_root_drive & 0x7f); if (grub_install_dos_part >= 0) grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1); diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 0bfe2b37d..0a38b994c 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008 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 @@ -162,6 +162,7 @@ multiboot_trampoline: movl %ebx, EXT_C(grub_install_bsd_part) 2: shrl $24, %edx + movb $0xFF, %dh /* enter the usual booting */ call prot_to_real .code16 @@ -182,8 +183,9 @@ codestart: sti /* we're safe again */ - /* save boot drive reference */ + /* save boot and root drive references */ ADDR32 movb %dl, EXT_C(grub_boot_drive) + ADDR32 movb %dh, EXT_C(grub_root_drive) /* reset disk system (%ah = 0) */ int $0x13 @@ -255,6 +257,9 @@ codestart: VARIABLE(grub_boot_drive) .long 0 +VARIABLE(grub_root_drive) + .long 0 + VARIABLE(grub_start_addr) .long START_SYMBOL