add the command map.

This commit is contained in:
okuji 1999-10-20 20:13:15 +00:00
parent 460515b963
commit 42afef19eb
6 changed files with 257 additions and 5 deletions

View file

@ -1,3 +1,27 @@
1999-10-21 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
Add BIOS drive remapping support for chain-loading some foolish
operating systems.
* stage2/builtins.c (bios_drive_map): New variable.
(boot_func): If KERNEL_TYPE is KERNEL_TYPE_CHAINLOADER, check
if BIOS_DRIVE_MAP contains meaningful values. If so, search for
SAVED_DRIVE in BIOS_DRIVE_MAP and exchange SAVED_DRIVE with the
mapped drive if found. And then call set_int13_handler.
(map_func): New function.
(builtin_map): New variable.
(builtin_table): Added a pointer to BUILTIN_MAP.
* stage2/asm.S (ABS): New macro.
[!STAGE1_5] (set_int13_handler): New function.
[!STAGE1_5] (int13_handler): New interrupt handler for the real
mode.
[!STAGE1_5] (drive_map): New variable.
[!STAGE1_5] (int13_handler_end): New label used for just
computing the end address of int13_handler.
* stage2/shared.h (DRIVE_MAP_SIZE): New macro.
(set_int13_handler): Declared.
* grub/asmstub.c (set_int13_handler): New function. Do nothing.
1999-10-20 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage2/builtins.c (find_func): Print only the device names.

3
NEWS
View file

@ -15,6 +15,9 @@ New in 0.5.94:
added.
* The command "find" searches for a filename in all devices and print
the list of the device which contain the file.
* The command "map" maps a drive to another drive so that we can
chain-load some foolish operating systems (such as DOS) even if such
an operating system resides at a non-first drive.
New in 0.5.93:
* ELF format of FreeBSD kernel is supported.

View file

@ -597,6 +597,12 @@ gateA20 (int linear)
/* Nothing to do in the simulator. */
}
/* Copy MAP to the drive map and set up the int13 handler. */
void
set_int13_handler (unsigned short *map)
{
/* Nothing to do in the simulator. */
}
int
get_code_end (void)

View file

@ -22,6 +22,12 @@
#include "shared.h"
#ifdef STAGE1_5
#define ABS(x) ((x) - EXT_C(main) + 0x2200)
#else
#define ABS(x) ((x) - EXT_C(main) + 0x8200)
#endif
.file "asm.S"
.text
@ -46,11 +52,7 @@ ENTRY(main)
* Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and
* at 0x0:0x2200 in stage1.5.
*/
#ifndef STAGE1_5
ljmp $0, $(codestart - EXT_C(main) + 0x8200)
#else
ljmp $0, $(codestart - EXT_C(main) + 0x2200)
#endif
ljmp $0, $ABS(codestart)
/*
* Compatibility version number
@ -153,6 +155,135 @@ ENTRY(stop_floppy)
outb %al, %dx
ret
/*
* set_int13_handler(map)
*
* Copy MAP to the drive map and set up int13_handler.
*/
ENTRY(set_int13_handler)
pushl %ebp
movl %esp, %ebp
pushl %ecx
pushl %edi
pushl %esi
/* copy MAP to the drive map */
movl $DRIVE_MAP_SIZE, %ecx
movl $ABS(drive_map), %edi
movl 4(%ebp), %esi
cld
rep
movsb
/* save the original int13 handler */
movw 0x13 * 4, %ax
movw %ax, int13_offset
movw 0x13 * 4 + 2, %ax
movw %ax, int13_segment
/* get the lower memory size */
movl $EXT_C(mbi), %edi
movl 4(%edi), %eax
/* decrease the lower memory size and set it to the BIOS memory */
decl %eax
movw %ax, 0x413
/* compute the segment */
shll $6, %eax
/* save the new int13 handler */
movw %ax, 0x13 * 4 + 2
xorw %ax, %ax
movw %ax, 0x13 * 4
/* copy int13_handler to the reserved area */
shll $4, %eax
movl %eax, %edi
movl $ABS(int13_handler), %esi
movl $(int13_handler_end - int13_handler), %ecx
rep
movsb
popl %esi
popl %edi
popl %ecx
popl %ebp
ret
/*
* Map a drive to another drive.
*/
.code16
int13_handler:
pushw %ax
pushw %bp
movw %sp, %bp
pushw %ds
pushw %si
/* set %ds to %cs */
movw %cs, %ax
movw %ax, %ds
/* set %si to the drive map */
movw $(drive_map - int13_handler), %si
/* find the drive number from the drive map */
1:
lodsw
/* check if this is the end */
testw %ax, %ax
jz 2f
/* check if this matches the drive number */
cmpb %al, %dl
jne 1b
/* if so, perform the mapping */
movb %ah, %dl
2:
/* restore %si and %ds */
popw %si
popw %ds
/* save %ax in the stack */
pushw %ax
/* set %ax and %bp to the original values */
movw 2(%bp), %ax
movw (%bp), %bp
/* simulate the interrupt call */
pushf
/* ljmp */
.byte 0x9a
int13_offset: .word 0
int13_segment: .word 0
/* restore %bp */
movw %sp, %bp
/* save %ax */
pushw %ax
/* check if should map the drive number */
movw 4(%bp), %ax
cmpw $0x8, %ax
jne 3f
cmpw $0x15, %ax
jne 3f
/* check if the mapping was performed */
movw (%bp), %ax
testw %ax, %ax
jz 3f
/* perform the mapping */
movb %al, %dl
3:
popw %ax
movw 2(%bp), %bp
addw $6, %sp
iret
drive_map: .space (DRIVE_MAP_SIZE + 1) * 2
int13_handler_end:
.code32
/*
* chain_stage1(segment, offset, part_table_addr)
*

View file

@ -46,6 +46,8 @@ int normal_color;
int highlight_color;
/* The timeout. */
int grub_timeout = -1;
/* The BIOS drive map. */
static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
/* Initialize the data for builtins. */
void
@ -101,6 +103,29 @@ boot_func (char *arg, int flags)
case KERNEL_TYPE_CHAINLOADER:
/* Chainloader */
/* Check if we should set the int13 handler. */
if (bios_drive_map[0] != 0)
{
int i;
/* Search for SAVED_DRIVE. */
for (i = 0; i <= DRIVE_MAP_SIZE; i++)
{
if (! bios_drive_map[i])
break;
else if ((bios_drive_map[i] & 0xFF) == saved_drive)
{
/* Exchage SAVED_DRIVE with the mapped drive. */
saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
break;
}
}
/* Set the handler. This is somewhat dangerous. */
set_int13_handler (bios_drive_map);
}
gateA20 (0);
boot_drive = saved_drive;
chain_stage1 (0, BOOTSEC_LOCATION, BOOTSEC_LOCATION - 16);
@ -1432,6 +1457,62 @@ static struct builtin builtin_makeactive =
" This command is limited to _primary_ PC partitions on a hard disk."
};
/* map */
/* Map FROM_DRIVE to TO_DRIVE. */
static int
map_func (char *arg, int flags)
{
char *to_drive;
char *from_drive;
unsigned long to, from;
int i;
to_drive = arg;
from_drive = skip_to (0, arg);
/* Get the drive number for TO_DRIVE. */
set_device (to_drive);
if (errnum)
return 1;
to = current_drive;
/* Get the drive number for FROM_DRIVE. */
set_device (from_drive);
if (errnum)
return 1;
from = current_drive;
/* If TO and FROM is the same, do nothing. */
if (to == from)
return 0;
/* Search for an empty slot in BIOS_DRIVE_MAP. */
for (i = 0; i <= DRIVE_MAP_SIZE; i++)
if (! bios_drive_map[i])
break;
if (i > DRIVE_MAP_SIZE)
{
errnum = ERR_WONT_FIT;
return 1;
}
bios_drive_map[i] = from | (to << 8);
return 0;
}
static struct builtin builtin_map =
{
"map",
map_func,
BUILTIN_CMDLINE,
"map TO_DRIVE FROM_DRIVE",
"Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary"
" when you chain-load some operating systems, such as DOS, if such a"
" OS resides at a non-first drive."
};
/* module */
static int
@ -2101,6 +2182,7 @@ struct builtin *builtin_table[] =
&builtin_install,
&builtin_kernel,
&builtin_makeactive,
&builtin_map,
&builtin_module,
&builtin_modulenounzip,
&builtin_password,

View file

@ -117,6 +117,9 @@ extern char *grub_scratch_mem;
#define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN)
#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF)
/* The size of the drive map. */
#define DRIVE_MAP_SIZE 8
/*
* Linux setup parameters
*/
@ -494,6 +497,9 @@ void cmain (void);
/* Halt the processor (called after an unrecoverable error). */
void stop (void) __attribute__ ((noreturn));
/* Copy MAP to the drive map and set up int13_handler. */
void set_int13_handler (unsigned short *map);
/* calls for direct boot-loader chaining */
void chain_stage1 (int segment, int offset, int part_table_addr)
__attribute__ ((noreturn));