diff --git a/ChangeLog b/ChangeLog index 198d8e55b..a4d8fca26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +1999-10-29 OKUJI Yoshinori + + * stage2/asm.S (track_int13): Defined unconditionally. Do not + use int3 any more, but replace the int13 handler with + set_tf_int13_handler. + (int1_handler): Defined unconditionally. Do not check for 0x0F. + Add missing `$'s. If the code is 0xEC-0xEF, use %dx instead of + immediate. If the code is 0xE4-0xE7, use immediate instead of + %dx. Set %ds to zero before scanning IO_MAP. Check for the + buffer overrun of IO_MAP before adding a port. + [!DEFINE_TRACK_INT13] (int13_first_instruction): Removed. + [!DEFINE_TRACK_INT13] (int3_handler): Likewise. + (set_tf_int13_handler): New interrupt handler. + (set_tf_int13_offset): New variable. + (set_tf_int13_segment): Likewise. + * stage2/builtins.c (ioprobe_func): New function. + (builtin_ioprobe): New variable. + (builtin_table): Added a pointer to BUILTIN_IOPROBE. + * stage2/shared.h (IO_MAP_SIZE): New macro. + (track_int13): Declared. + (io_map): Likewise. + 1999-10-29 OKUJI Yoshinori * stage2/char_io.c (print_error) [!STAGE1_5]: Print "Error:" diff --git a/NEWS b/NEWS index f657d2894..c15b9326f 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ New in 0.5.94: * The command "setkey" maps a key to another. * The GRUB manual is rewritten, and now consists of three parts and appendices. +* The command "ioprobe" detects what I/O ports are used for a BIOS + drive. New in 0.5.93: * ELF format of FreeBSD kernel is supported. diff --git a/stage2/asm.S b/stage2/asm.S index f685268c4..86ec4fdbe 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -186,8 +186,7 @@ ENTRY(stop_floppy) outb %al, %dx ret - -#ifdef DEFINE_TRACK_INT13 + /* * track_int13(int drive) * @@ -201,40 +200,29 @@ ENTRY(track_int13) pushl %ebx pushl %edi - /* computer the linear address of int13 handler */ + /* save the original int13 handler */ movl $0x4c, %edi - xorl %ebx, %ebx - xorl %eax, %eax + movw (%edi), %ax + movw %ax, ABS(set_tf_int13_offset) movw 2(%edi), %ax - shll $4, %eax - movw (%edi), %bx - addl %eax, %ebx - - /* save the first intruction */ - movb (%ebx), %al - movb %al, ABS(int13_first_instruction) - - /* set the first instruction to int3 */ - movb $0xCC, (%ebx) + movw %ax, ABS(set_tf_int13_segment) + /* save the new int13 handler */ + movl $ABS(set_tf_int13_handler), %eax + movl %eax, (%edi) + /* replace the int1 handler */ - movl 0x4, %edi + movl $0x4, %edi pushl (%edi) movl $ABS(int1_handler), %eax movl %eax, (%edi) - /* replace the int3 handler */ - movl 0xc, %edi - pushl (%edi) - movl $ABS(int3_handler), %eax - movl %eax, (%edi) - /* read the MBR to call int13 successfully */ movb 8(%ebp), %dl - DATA32 call EXT_C(prot_to_real) + call EXT_C(prot_to_real) .code16 - + movw $SCRATCHSEG, %ax movw %ax, %es xorw %bx, %bx @@ -247,13 +235,16 @@ ENTRY(track_int13) DATA32 call EXT_C(real_to_prot) .code32 - /* restore the int3 handler */ - movl 0xc, %edi + /* restore the int1 handler */ + movl $0x4, %edi popl (%edi) - /* restore the int1 handler */ - movl 0x4, %edi - popl (%edi) + /* restore the int13 handler */ + movl $0x4c, %edi + movw ABS(set_tf_int13_offset), %ax + movw %ax, (%edi) + movw ABS(set_tf_int13_segment), %ax + movw %ax, 2(%edi) popl %edi popl %ebx @@ -299,15 +290,13 @@ int1_handler: je 1b cmpb $0x26, %al je 1b - cmpb $0x0F, %al - je 1b cmpb $0x64, %al jl 2f cmpb $0x67, %al jle 1b -2: cmpb 0xF0, %al +2: cmpb $0xF0, %al jl 3f - cmpb 0xF3, %al + cmpb $0xF3, %al jle 1b 3: /* check if this code is out* or in* */ @@ -318,13 +307,13 @@ int1_handler: cmpb $0x6F, %al jle 5f -4: /* in? or out? (immediate operand version) */ +4: /* in? or out? (register operand version) */ cmpb $0xEC, %al jl 6f cmpb $0xEF, %al - jle 7f + jle 5f -6: /* in? or out? (register operand version) */ +6: /* in? or out? (immediate operand version) */ cmpb $0xE4, %al jl 8f cmpb $0xE7, %al @@ -337,6 +326,10 @@ int1_handler: 5: /* %dx has a port */ + /* set %ds to zero */ + xorw %ax, %ax + movw %ax, %ds + /* set %si to the io map */ movw $ABS(io_map), %si @@ -352,7 +345,10 @@ int1_handler: /* if so, leave from this handler */ jmp 8f -1: /* add the port into the io map */ +1: /* check for the buffer overrun */ + cmpw $(ABS(io_map) + (IO_MAP_SIZE + 1) * 2), %si + je 8f + /* add the port into the io map */ movw %dx, -2(%si) 8: /* restore registers */ @@ -370,52 +366,36 @@ int1_handler: * call clears the flag automatically. * * Note: we need not to clear this flag after the tracking explicitly, - * because int13 restores the original FLAGS. - * - * Note2: In this implementation, ignore the first instruction, because - * int1 is a trap but not a fault. + * because iret restores the original FLAGS. */ -int13_first_instruction: - .byte 0 - -int3_handler: - pushw %bp - movw %sp, %bp +set_tf_int13_handler: + /* save %ax int the stack */ pushw %ax - pushw %bx - pushw %ds - /* set the TF flag in the stack */ - movw 6(%bp), %ax - orw $0x100, %ax - movw %ax, 6(%bp) - - /* restore the first instruction */ - movb ABS(int13_first_instruction), %al - movw 4(%bp), %bx - movw %bx, %ds - movw 2(%bp), %bx - decw %bx - movb %al, (%bx) - - /* re-execute the first instruction */ - movw %bx, 2(%bp) - - popw %ds - popw %bx + /* set the TF flag */ + pushf popw %ax - popw %bp - + orw $0x100, %ax + pushw %ax + popf + + /* restore %ax */ + popw %ax + + /* simulate the interrupt call */ + pushf + /* lcall */ + .byte 0x9a +set_tf_int13_offset: .word 0 +set_tf_int13_segment: .word 0 + iret .code32 ENTRY(io_map) -#define IO_MAP_SIZE 0 .space (IO_MAP_SIZE + 1) * 2 -#endif /* DEFINE_TRACK_INT13 */ - /* * set_int15_handler(void) diff --git a/stage2/builtins.c b/stage2/builtins.c index 0d935cce0..de2a5d4fd 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -1441,6 +1441,49 @@ static struct builtin builtin_install = " this is the name of the true Stage 2) at boot time." }; + +/* ioprobe */ +static int +ioprobe_func (char *arg, int flags) +{ +#ifdef GRUB_UTIL + + errnum = ERR_UNRECOGNIZED; + return 1; + +#else /* ! GRUB_UTIL */ + + unsigned short *port; + + /* Get the drive number. */ + set_device (arg); + if (errnum) + return 1; + + /* Clean out IO_MAP. */ + grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short)); + + /* Track the int13 handler. */ + track_int13 (current_drive); + + /* Print out the result. */ + for (port = io_map; *port != 0; port++) + grub_printf (" 0x%x", (unsigned int) *port); + + return 0; + +#endif /* ! GRUB_UTIL */ +} + +static struct builtin builtin_ioprobe = +{ + "ioprobe", + ioprobe_func, + BUILTIN_CMDLINE, + "ioprobe DRIVE", + "Probe I/O ports used for the drive DRIVE." +}; + /* kernel */ static int @@ -2470,6 +2513,7 @@ struct builtin *builtin_table[] = &builtin_impsprobe, &builtin_initrd, &builtin_install, + &builtin_ioprobe, &builtin_kernel, &builtin_makeactive, &builtin_map, diff --git a/stage2/shared.h b/stage2/shared.h index 1967b6078..2b425ce61 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -123,6 +123,8 @@ extern char *grub_scratch_mem; /* The size of the key map. */ #define KEY_MAP_SIZE 128 +/* The size of the io map. */ +#define IO_MAP_SIZE 128 /* * Linux setup parameters @@ -538,9 +540,13 @@ void set_int15_handler (void); /* Restore the original int15 handler. */ void unset_int15_handler (void); +/* Track the int13 handler to probe I/O address space. */ +void track_int13 (int drive); + /* The key map. */ extern unsigned short bios_key_map[]; extern unsigned short ascii_key_map[]; +extern unsigned short io_map[]; /* calls for direct boot-loader chaining */ void chain_stage1 (int segment, int offset, int part_table_addr)