fix many bugs in the BIOS drive remapping feature.

This commit is contained in:
okuji 1999-10-26 09:02:38 +00:00
parent 9d7344365c
commit 482c5a1631
4 changed files with 86 additions and 46 deletions

View file

@ -1,3 +1,26 @@
1999-10-26 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
Now the BIOS drive remapping is functional.
* stage2/asm.S [DEFINE_TRACK_INT13] (track_int13): Use %edi
instead of direct addresses.
Prefix DATA32 to the calls for real_to_prot and prot_to_real.
Fix the address of DRIVE: 4(%ebp) -> 8(%ebp).
(set_int15_handler): Use %edi instead of direct addresses.
(unset_int15_handler): Likewise.
(set_int13_handler): Copy DRIVE_MAP_SIZE * 2 bytes instead of
DRIVE_MAP_SIZE bytes of MAP.
Fix the address of MAP: 4(%ebp) -> 8(%ebp).
Use %edi instead of direct addresses.
(int13_handler): Do not set %ds to %cs. Use the segment override
prefix of %cs instead.
Push the flags pushed by the callee instead of the current.
Set the flags in the stack to the flags returned by the original
int13 call.
(drive_map): 4bytes-aligned.
* stage2/disk_io.c (grub_close): Do not set ERRNUM even if
FSYS_TYPE is NUM_FSYS.
1999-10-25 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage1/stage1.S: Long jump to real_start, because some bogus

View file

@ -199,13 +199,15 @@ ENTRY(track_int13)
pushl %edx
pushl %ebx
pushl %edi
/* computer the linear address of int13 handler */
movl $0x4c, %edi
xorl %ebx, %ebx
xorl %eax, %eax
movw 0x13 * 4 + 2, %ax
movw 2(%edi), %ax
shll $4, %eax
movw 0x13 * 4, %bx
movw (%edi), %bx
addl %eax, %ebx
/* save the first intruction */
@ -216,19 +218,21 @@ ENTRY(track_int13)
movb $0xCC, (%ebx)
/* replace the int1 handler */
pushl 0x1 * 4
movl 0x4, %edi
pushl (%edi)
movl $ABS(int1_handler), %eax
movl %eax, 0x1 * 4
movl %eax, (%edi)
/* replace the int3 handler */
pushl 0x3 * 4
movl 0xc, %edi
pushl (%edi)
movl $ABS(int3_handler), %eax
movl %eax, 0x3 * 4
movl %eax, (%edi)
/* read the MBR to call int13 successfully */
movb 4(%ebp), %dl
movb 8(%ebp), %dl
call prot_to_real
DATA32 call EXT_C(prot_to_real)
.code16
movw $SCRATCHSEG, %ax
@ -240,15 +244,18 @@ ENTRY(track_int13)
movw $0x201, %ax
int $0x13
call real_to_prot
DATA32 call EXT_C(real_to_prot)
.code32
/* restore the int3 handler */
popl 0x3 * 4
movl 0xc, %edi
popl (%edi)
/* restore the int1 handler */
popl 0x1 * 4
movl 0x4, %edi
popl (%edi)
popl %edi
popl %ebx
popl %edx
popl %ebp
@ -416,19 +423,23 @@ ENTRY(io_map)
* Set up int15_handler.
*/
ENTRY(set_int15_handler)
pushl %edi
/* save the original int15 handler */
movw 0x15 * 4, %ax
movl $0x54, %edi
movw (%edi), %ax
movw %ax, ABS(int15_offset)
movw 0x15 * 4 + 2, %ax
movw 2(%edi), %ax
movw %ax, ABS(int15_segment)
/* save the new int15 handler */
movl $ABS(int15_handler), %eax
rorl $4, %eax
movw %ax, 0x15 * 4 + 2
movw %ax, 2(%edi)
shrl $28, %eax
movw %ax, 0x15 * 4
movw %ax, (%edi)
popl %edi
ret
@ -438,22 +449,26 @@ ENTRY(set_int15_handler)
* Restore the original int15 handler
*/
ENTRY(unset_int15_handler)
pushl %edi
/* check if int15_handler is set */
movl $0x54, %edi
movl $ABS(int15_handler), %eax
rorl $4, %eax
cmpw %ax, 0x15 * 4 + 2
cmpw %ax, 2(%edi)
jne 1f
shrl $28, %eax
cmpw %ax, 0x15 * 4
cmpw %ax, (%edi)
jne 1f
/* restore the original */
movw ABS(int15_offset), %ax
movw %ax, 0x15 * 4
movw %ax, (%edi)
movw ABS(int15_segment), %ax
movw %ax, 0x15 * 4 + 2
movw %ax, 2(%edi)
1:
popl %edi
ret
@ -525,17 +540,18 @@ ENTRY(set_int13_handler)
pushl %esi
/* copy MAP to the drive map */
movl $DRIVE_MAP_SIZE, %ecx
movl $(DRIVE_MAP_SIZE * 2), %ecx
movl $ABS(drive_map), %edi
movl 4(%ebp), %esi
movl 8(%ebp), %esi
cld
rep
movsb
/* save the original int13 handler */
movw 0x13 * 4, %ax
movl $0x4c, %edi
movw (%edi), %ax
movw %ax, ABS(int13_offset)
movw 0x13 * 4 + 2, %ax
movw 2(%edi), %ax
movw %ax, ABS(int13_segment)
/* get the lower memory size */
@ -543,14 +559,16 @@ ENTRY(set_int13_handler)
movl 4(%edi), %eax
/* decrease the lower memory size and set it to the BIOS memory */
decl %eax
movw %ax, 0x413
movl $0x413, %edi
movw %ax, (%edi)
/* compute the segment */
shll $6, %eax
/* save the new int13 handler */
movw %ax, 0x13 * 4 + 2
xorw %ax, %ax
movw %ax, 0x13 * 4
movl $0x4c, %edi
movw %ax, 2(%edi)
xorw %cx, %cx
movw %cx, (%edi)
/* copy int13_handler to the reserved area */
shll $4, %eax
@ -565,7 +583,7 @@ ENTRY(set_int13_handler)
popl %ecx
popl %ebp
ret
/*
* Map a drive to another drive.
@ -578,17 +596,14 @@ int13_handler:
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 */
cld
1:
lodsw
lodsw %cs:(%si), %ax
/* check if this is the end */
testw %ax, %ax
jz 2f
@ -598,42 +613,47 @@ int13_handler:
/* if so, perform the mapping */
movb %ah, %dl
2:
/* restore %si and %ds */
/* restore %si */
popw %si
popw %ds
/* save %ax in the stack */
pushw %ax
/* simulate the interrupt call */
pushw 8(%bp)
/* 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
/* save flags */
pushf
/* restore %bp */
movw %sp, %bp
/* save %ax */
pushw %ax
/* set the flags in the stack to the value returned by int13 */
movw (%bp), %ax
movw %ax, 0xc(%bp)
/* check if should map the drive number */
movw 4(%bp), %ax
movw 6(%bp), %ax
cmpw $0x8, %ax
jne 3f
cmpw $0x15, %ax
jne 3f
/* check if the mapping was performed */
movw (%bp), %ax
movw 2(%bp), %ax
testw %ax, %ax
jz 3f
/* perform the mapping */
movb %al, %dl
3:
popw %ax
movw 2(%bp), %bp
addw $6, %sp
movw 4(%bp), %bp
addw $8, %sp
iret
.align 4
drive_map: .space (DRIVE_MAP_SIZE + 1) * 2
int13_handler_end:

View file

@ -131,7 +131,7 @@ boot_func (char *arg, int flags)
/* 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);

View file

@ -1518,10 +1518,7 @@ void
grub_close (void)
{
if (fsys_type == NUM_FSYS)
{
errnum = ERR_FSYS_MOUNT;
return;
}
return;
if (fsys_table[fsys_type].close_func == 0)
return;