2009-06-11 Vladimir Serbinenko <phcoder@gmail.com>

Drivemap fixes

	* commands/i386/pc/drivemap.c (grub_get_root_biosnumber_drivemap):
	new function
	(grub_get_root_biosnumber_saved): new variable
	(GRUB_MOD_INIT): register grub_get_root_biosnumber_drivemap
	(GRUB_MOD_FINI): unregister grub_get_root_biosnumber_drivemap
	* commands/i386/pc/drivemap_int13h.S (grub_drivemap_handler): restore 
	%dx after the call if necessary
	* conf/common.rmk (pkglib_MODULES): remove boot.mod
	(boot_mod_SOURCES): remove
	(boot_mod_CFLAGS): remove
	(boot_mod_LDFLAGS): remove
	* conf/i386-coreboot.rmk (pkglib_MODULES): add boot.mod
	(boot_mod_SOURCES): new variable
	(boot_mod_CFLAGS): likewise
	(boot_mod_LDFLAGS): likewise
	* conf/i386-efi.rmk: likewise
	* conf/i386-ieee1275.rmk: likewise
	* conf/i386-pc.rmk: likewise
	* conf/powerpc-ieee1275.rmk: likewise
	* conf/sparc64-ieee1275.rmk: likewise
	* conf/x86_64-efi.rmk: likewise
	* include/grub/i386/pc/biosnum.h: new file
	* lib/i386/pc/biosnum.c: likewise
	* loader/i386/bsd.c (grub_bsd_get_device): use grub_get_root_biosnumber
	* loader/i386/multiboot.c (grub_multiboot_get_bootdev): likewise
	* loader/i386/pc/chainloader.c (grub_chainloader_cmd): likewise
This commit is contained in:
phcoder 2009-06-11 16:13:39 +00:00
parent 5ac35b35b0
commit 63963d17d0
16 changed files with 269 additions and 67 deletions

View file

@ -1,3 +1,34 @@
2009-06-11 Vladimir Serbinenko <phcoder@gmail.com>
Drivemap fixes
* commands/i386/pc/drivemap.c (grub_get_root_biosnumber_drivemap):
new function
(grub_get_root_biosnumber_saved): new variable
(GRUB_MOD_INIT): register grub_get_root_biosnumber_drivemap
(GRUB_MOD_FINI): unregister grub_get_root_biosnumber_drivemap
* commands/i386/pc/drivemap_int13h.S (grub_drivemap_handler): restore
%dx after the call if necessary
* conf/common.rmk (pkglib_MODULES): remove boot.mod
(boot_mod_SOURCES): remove
(boot_mod_CFLAGS): remove
(boot_mod_LDFLAGS): remove
* conf/i386-coreboot.rmk (pkglib_MODULES): add boot.mod
(boot_mod_SOURCES): new variable
(boot_mod_CFLAGS): likewise
(boot_mod_LDFLAGS): likewise
* conf/i386-efi.rmk: likewise
* conf/i386-ieee1275.rmk: likewise
* conf/i386-pc.rmk: likewise
* conf/powerpc-ieee1275.rmk: likewise
* conf/sparc64-ieee1275.rmk: likewise
* conf/x86_64-efi.rmk: likewise
* include/grub/i386/pc/biosnum.h: new file
* lib/i386/pc/biosnum.c: likewise
* loader/i386/bsd.c (grub_bsd_get_device): use grub_get_root_biosnumber
* loader/i386/multiboot.c (grub_multiboot_get_bootdev): likewise
* loader/i386/pc/chainloader.c (grub_chainloader_cmd): likewise
2009-06-10 Pavel Roskin <proski@gnu.org>
* io/gzio.c (test_header): Don't reuse one buffer for all data.

View file

@ -23,8 +23,9 @@
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/loader.h>
#include <grub/env.h>
#include <grub/machine/memory.h>
#include <grub/machine/biosnum.h>
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
@ -356,10 +357,49 @@ uninstall_int13_handler (void)
return GRUB_ERR_NONE;
}
static int
grub_get_root_biosnumber_drivemap (void)
{
char *biosnum;
int ret = -1;
grub_device_t dev;
biosnum = grub_env_get ("biosnum");
if (biosnum)
return grub_strtoul (biosnum, 0, 0);
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->dev
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
{
drivemap_node_t *curnode = map_head;
ret = (int) dev->disk->id;
while (curnode)
{
if (curnode->redirto == ret)
{
ret = curnode->newdrive;
break;
}
curnode = curnode->next;
}
}
if (dev)
grub_device_close (dev);
return ret;
}
static grub_extcmd_t cmd;
static int (*grub_get_root_biosnumber_saved) (void);
GRUB_MOD_INIT (drivemap)
{
grub_get_root_biosnumber_saved = grub_get_root_biosnumber;
grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap;
cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap,
GRUB_COMMAND_FLAG_BOTH,
"drivemap"
@ -374,6 +414,7 @@ GRUB_MOD_INIT (drivemap)
GRUB_MOD_FINI (drivemap)
{
grub_get_root_biosnumber = grub_get_root_biosnumber_saved;
grub_loader_unregister_preboot_hook (drivemap_hook);
drivemap_hook = 0;
grub_unregister_extcmd (cmd);

View file

@ -27,6 +27,11 @@
/* The replacement int13 handler. Preserve all registers. */
FUNCTION(grub_drivemap_handler)
/* Save %dx for future restore. */
push %dx
/* Push flags. Used to simulate interrupt with original flags. */
pushf
/* Map the drive number (always in DL). */
push %ax
push %bx
@ -51,10 +56,47 @@ not_found:
pop %bx
pop %ax
/* Upon arrival to this point the stack must be exactly like at entry.
This long jump will transfer the caller's stack to the old INT13
handler, thus making it return directly to the original caller. */
.byte 0xea
cmpb $0x8, %ah
jz norestore
cmpb $0x15, %ah
jz norestore
/* Restore flags. */
popf
pushf
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
push %bp
mov %sp, %bp
tail:
pushf
pop %dx
mov %dx, 8(%bp)
pop %bp
/* Restore %dx. */
pop %dx
iret
norestore:
/* Restore flags. */
popf
pushf
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
push %bp
mov %sp, %bp
/* Save %dx. */
mov %dx, 2(%bp)
jmp tail
/* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode
IVT entries (thus PI:SC in mem). */

View file

@ -353,7 +353,7 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \
loopback.mod fs_uuid.mod configfile.mod echo.mod \
terminfo.mod test.mod blocklist.mod hexdump.mod \
read.mod sleep.mod loadenv.mod crc.mod parttool.mod \
pcpart.mod memrw.mod boot.mod normal.mod sh.mod lua.mod \
pcpart.mod memrw.mod normal.mod sh.mod lua.mod \
gptsync.mod true.mod
# For gptsync.mod.
@ -361,11 +361,6 @@ gptsync_mod_SOURCES = commands/gptsync.c
gptsync_mod_CFLAGS = $(COMMON_CFLAGS)
gptsync_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For boot.mod.
boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For minicmd.mod.
minicmd_mod_SOURCES = commands/minicmd.c
minicmd_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -109,6 +109,12 @@ pkglib_MODULES = linux.mod multiboot.mod \
halt.mod datetime.mod date.mod datehook.mod \
lsmmap.mod mmap.mod
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For mmap.mod.
mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c
mmap_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -117,6 +117,12 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.
kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For acpi.mod.
acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c
acpi_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -108,6 +108,12 @@ pkglib_MODULES = halt.mod reboot.mod suspend.mod \
nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
date.mod datehook.mod lsmmap.mod mmap.mod
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For mmap.mod.
mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c
mmap_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -189,6 +189,12 @@ pkglib_MODULES = biosdisk.mod chain.mod \
usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \
efiemu.mod mmap.mod acpi.mod drivemap.mod
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For drivemap.mod.
drivemap_mod_SOURCES = commands/i386/pc/drivemap.c \
commands/i386/pc/drivemap_int13h.S

View file

@ -119,6 +119,12 @@ pkglib_MODULES = halt.mod \
memdisk.mod \
lsmmap.mod
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For linux.mod.
linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
linux_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -149,6 +149,12 @@ pkglib_MODULES = halt.mod \
memdisk.mod \
lsmmap.mod
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For linux.mod.
linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c
linux_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -115,6 +115,12 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.
kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
# For boot.mod.
pkglib_MODULES += boot.mod
boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For acpi.mod.
acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c
acpi_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -0,0 +1,6 @@
#ifndef GRUB_BIOSNUM_MACHINE_HEADER
#define GRUB_BIOSNUM_MACHINE_HEADER 1
extern int (*grub_get_root_biosnumber) (void);
#endif

46
lib/i386/pc/biosnum.c Normal file
View file

@ -0,0 +1,46 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/env.h>
#include <grub/misc.h>
#include <grub/disk.h>
static int
grub_get_root_biosnumber_default (void)
{
char *biosnum;
int ret = -1;
grub_device_t dev;
biosnum = grub_env_get ("biosnum");
if (biosnum)
return grub_strtoul (biosnum, 0, 0);
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->dev
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
ret = (int) dev->disk->id;
if (dev)
grub_device_close (dev);
return ret;
}
int (*grub_get_root_biosnumber) (void) = grub_get_root_biosnumber_default;

View file

@ -33,6 +33,12 @@
#include <grub/gzio.h>
#include <grub/aout.h>
#include <grub/command.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#endif
#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
#define ALIGN_QWORD(a) ALIGN_UP (a, 8)
@ -81,23 +87,22 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
grub_uint32_t * slice, grub_uint32_t * part)
{
char *p;
grub_device_t dev;
*biosdev = *unit = *slice = *part = 0;
p = grub_env_get ("root");
if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
(p[2] >= '0') && (p[2] <= '9'))
*biosdev = grub_get_root_biosnumber () & 0xff;
*unit = (*biosdev & 0x7f);
*slice = 0xff;
*part = 0xff;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
if (p[0] == 'h')
*biosdev = 0x80;
*unit = grub_strtoul (p + 2, &p, 0);
*biosdev += *unit;
if ((p) && (p[0] == ','))
p = dev->disk->partition->partmap->get_name (dev->disk->partition);
if (p)
{
if ((p[1] >= '0') && (p[1] <= '9'))
if ((p[0] >= '0') && (p[0] <= '9'))
{
*slice = grub_strtoul (p + 1, &p, 0);
*slice = grub_strtoul (p, &p, 0);
if ((p) && (p[0] == ','))
p++;
@ -107,6 +112,8 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
*part = p[0] - 'a';
}
}
if (dev)
grub_device_close (dev);
}
static grub_err_t

View file

@ -42,6 +42,12 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#endif
extern grub_dl_t my_mod;
static struct grub_multiboot_info *mbi, *mbi_dest;
@ -148,46 +154,42 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer)
static int
grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
{
#ifdef GRUB_MACHINE_PCBIOS
char *p;
grub_uint32_t biosdev, slice = ~0, part = ~0;
grub_device_t dev;
p = grub_env_get ("root");
if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
(p[2] >= '0') && (p[2] <= '9'))
{
grub_uint32_t bd;
biosdev = grub_get_root_biosnumber ();
bd = (p[0] == 'h') ? 0x80 : 0;
bd += grub_strtoul (p + 2, &p, 0);
bd <<= 24;
if ((p) && (p[0] == ','))
{
if ((p[1] >= '0') && (p[1] <= '9'))
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
bd += ((grub_strtoul (p + 1, &p, 0) - 1) & 0xFF) << 16;
p = dev->disk->partition->partmap->get_name (dev->disk->partition);
if (p)
{
if ((p[0] >= '0') && (p[0] <= '9'))
{
slice = grub_strtoul (p, &p, 0);
if ((p) && (p[0] == ','))
p++;
}
else
bd += 0xFF0000;
if ((p[0] >= 'a') && (p[0] <= 'z'))
bd += (p[0] - 'a') << 8;
else
bd += 0xFF00;
part = p[0] - 'a';
}
else
bd += 0xFFFF00;
bd += 0xFF;
*bootdev = bd;
return 1;
}
if (dev)
grub_device_close (dev);
*bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16)
| ((part & 0xff) << 16) | 0xff;
return (biosdev != ~0UL);
#else
*bootdev = 0xffffffff;
return 0;
#endif
}
void

View file

@ -31,6 +31,7 @@
#include <grub/machine/memory.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/machine/biosnum.h>
static grub_dl_t my_mod;
static int boot_drive;
@ -89,29 +90,18 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
grub_file_close (file);
/* Obtain the partition table from the root device. */
drive = grub_get_root_biosnumber ();
dev = grub_device_open (0);
if (dev)
if (dev && dev->disk && dev->disk->partition)
{
grub_disk_t disk = dev->disk;
if (disk)
{
grub_partition_t p = disk->partition;
/* In i386-pc, the id is equal to the BIOS drive number. */
drive = (int) disk->id;
if (p)
{
grub_disk_read (disk, p->offset, 446, 64,
grub_disk_read (dev->disk, dev->disk->partition->offset, 446, 64,
(void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
+ (p->index << 4));
}
+ (dev->disk->partition->index << 4));
}
if (dev)
grub_device_close (dev);
}
/* Ignore errors. Perhaps it's not fatal. */
grub_errno = GRUB_ERR_NONE;