add the command map.
This commit is contained in:
parent
460515b963
commit
42afef19eb
6 changed files with 257 additions and 5 deletions
24
ChangeLog
24
ChangeLog
|
@ -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
3
NEWS
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
141
stage2/asm.S
141
stage2/asm.S
|
@ -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)
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue