Add two new versions of the mbr code that directly access a serial port.

'mbr_com0' assumes the BIOS has initialised the baud rate (etc)
'mbr_com0_9600' initialises the rate to 9600
Both have the functionality from 'mbr_ext' (ie they can boot from an
  extended partition).
As compiled, the io_address for the serial port is taken from BIOS data.
(this should keep tls@ happy!)
This commit is contained in:
dsl 2008-01-19 21:01:34 +00:00
parent 55433fb5ee
commit 3305a48bee
4 changed files with 140 additions and 21 deletions

View File

@ -1,5 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/28 12:19:05 dsl Exp $
# $NetBSD: Makefile,v 1.2 2008/01/19 21:01:34 dsl Exp $
SUBDIR= mbr mbr_bootsel mbr_ext
SUBDIR= mbr mbr_bootsel mbr_ext mbr_com0 mbr_com0_9600
.include <bsd.subdir.mk>

View File

@ -1,4 +1,4 @@
/* $NetBSD: mbr.S,v 1.15 2008/01/08 18:31:56 dsl Exp $ */
/* $NetBSD: mbr.S,v 1.16 2008/01/19 21:01:34 dsl Exp $ */
/*
* Copyright (c) 1999-2004 The NetBSD Foundation, Inc.
@ -44,10 +44,14 @@
/* Compile options:
* BOOTSEL - bootselector code
* BOOT_EXTENDED - scan extended partition list (LBA reads)
* COM_PORT - do serial io to specified port number
* 0..3 => bios port, otherwise actual io_addr
* COM_BAUD - initialise serial port baud rate
*
* TERSE_ERROR - terse error messages
* NO_CHS - all reads are LBA
* NO_LBA_CHECK - no check if bios supports LBA reads
* NO_BANNER - do not output 'banner'
* NO_BANNER - do not output title line 'banner'
*/
#ifdef BOOT_EXTENDED
@ -55,6 +59,19 @@
#define BOOTSEL 1
#endif
#ifdef COM_PORT
#if COM_PORT < 4
/* The first 4 items in the 40:xx segment are the serial port base addresses */
#define COM_PORT_VAL (0x400 + (COM_PORT * 2))
#else
#define COM_PORT_VAL $COM_PORT
#endif
#if !defined(COM_FREQ)
#define COM_FREQ 1843200
#endif
#endif
#ifdef BOOTSEL
#define TERSE_ERROR 1
#endif
@ -68,11 +85,22 @@
#define TABENTRYSIZE (MBR_BS_PARTNAMESIZE + 1)
#define NAMETABSIZE (MBR_PART_COUNT * TABENTRYSIZE)
#ifdef COM_PORT
/* ASCII values for the keys */
#define KEY_ACTIVE '\m'
#define KEY_DISK1 'a'
#define KEY_PTN1 '1'
#else
/* Scan values for the various keys we use, as returned by the BIOS */
#define SCAN_ENTER 0x1c
#define SCAN_F1 0x3b
#define SCAN_1 0x2
#define KEY_ACTIVE SCAN_ENTER
#define KEY_DISK1 SCAN_F1
#define KEY_PTN1 SCAN_1
#endif
/*
* Minimum and maximum drive number that is considered to be valid.
*/
@ -110,7 +138,7 @@ ENTRY(start)
mov %ax, %ds
movw $mbr, %di
mov $mbr - LOADADDR + BOOTADDR, %si
push %ax
push %ax /* zero for %cs of lret */
push %di
movw $(bss_start - mbr), %cx
rep
@ -118,7 +146,7 @@ ENTRY(start)
mov $(bss_end - bss_start + 1)/2, %cx
rep
stosw /* zero bss */
lret /* Ensure %cs == 0 */
lret /* Ensures %cs == 0 */
/*
* Sanity check the drive number passed by the BIOS. Some BIOSs may not
@ -132,6 +160,16 @@ mbr:
push %dx /* save drive number */
push %dx /* twice - for err_msg loop */
#if defined(COM_PORT) && defined(COM_BAUD)
mov $com_args, %si
mov $num_com_args, %cl /* %ch is zero from above */
mov COM_PORT_VAL, %dx
1: lodsw
add %ah, %dl
outb %dx
loop 1b
#endif
#ifndef NO_BANNER
mov $banner, %si
call message_crlf
@ -139,6 +177,15 @@ mbr:
/*
* Walk through the selector (name) table printing used entries.
*
* Register use:
* %ax temp
* %bx nametab[] boot seletor menu
* %ecx base of 'extended' partition
* %edx next extended partition
* %si message ptr (etc)
* %edi sector number of this partition
* %bp parttab[] mbr partition table
*/
bootsel_menu:
movw $nametab, %bx
@ -169,11 +216,11 @@ next_ptn:
je 4f
cmpb $0x80, (%bp) /* check for active partition */
jne 3f /* jump if not... */
#define ENTER (4 * ((SCAN_ENTER - SCAN_F1) & 0xff))
#define ACTIVE (4 * ((KEY_ACTIVE - KEY_DISK1) & 0xff))
#ifdef NO_CHS
movl %edi, ptn_list + ENTER /* save location of active ptn */
movl %edi, ptn_list + ACTIVE /* save location of active ptn */
#else
mov %bp, ptn_list + ENTER
mov %bp, ptn_list + ACTIVE
#endif
#undef ENTER
3:
@ -186,7 +233,7 @@ next_ptn:
call message /* menu number */
mov (%si), %si /* ':' << 8 | '1' + count */
shl $2, %si /* const + count * 4 */
#define CONST (4 * ((':' << 8) + '1' - ((SCAN_1 - SCAN_F1) & 0xff)))
#define CONST (4 * ((':' << 8) + '1' - ((KEY_PTN1 - KEY_DISK1) & 0xff)))
#ifdef NO_CHS
movl %edi, ptn_list - CONST(%si) /* sector to read */
#else
@ -228,7 +275,7 @@ next_ptn:
*/
#ifndef BOOTSEL
mov $(SCAN_ENTER - SCAN_F1) & 0xff, %ax
mov $(KEY_ACTIVE - KEY_DISK1) & 0xff, %ax
#else
/*
* Get the initial time value for the timeout comparison. It is returned
@ -244,21 +291,34 @@ wait_key:
int $0x1a
mov %dx, %di /* start time to di */
3:
#ifdef COM_PORT
mov COM_PORT_VAL, %dx
push %dx
add $5, %dx
inb %dx
pop %dx
test $1, %al
jz 1f
inb %dx
jmp check_key
#else
movb $1, %ah /* looks to see if a */
int $0x16 /* key has been pressed */
jnz get_key
jz 1f
get_key:
xorb %ah, %ah
int $0x16 /* 'read key', code ah, ascii al */
shr $8, %ax /* code in %al, %ah zero */
jmp check_key
#endif
1: xorb %ah, %ah
int $0x1a /* current time to cx:dx */
sub %di, %dx
cmpw timeout, %dx /* always wait for 1 tick... */
jbe 3b /* 0xffff means never timeout */
def_key:
mov defkey - 1, %ax /* timedout - get default key to %ah */
jmp 4f
get_key:
xorb %ah, %ah
int $0x16 /* 'read key', code ah, ascii al */
4: shr $8, %ax /* code in %al, %ah zero */
/*
* We have a keycode, see what it means.
@ -272,7 +332,7 @@ check_key:
* If we trust loc 475, we needn't check the upper bound on the keystroke
* This is always sector 0, so always read using chs.
*/
subb $SCAN_F1, %al
subb $KEY_DISK1, %al
cmpb 0x0475, %al
jae boot_ptn
addb $0x80, %al
@ -325,9 +385,10 @@ err_msg:
movw $errtxt, %si
call message
#else
push %ax
movw $errtxt, %si
call message
mov %ax, %si
pop %si
call message_crlf
#endif
pop %dx /* drive we errored on */
@ -337,7 +398,11 @@ err_msg:
pop %dx /* original drive number */
push %dx
push %dx
jmp get_key
#ifdef COM_PORT
jmp wait_key /* Read with timeout (again) */
#else
jmp get_key /* Blocking read */
#endif
#else
int $0x18 /* BIOS might ask for a key */
/* press and retry boot seq. */
@ -494,7 +559,11 @@ crlf: .asciz "\r\n"
#ifndef NO_BANNER
#ifdef BOOTSEL
#ifdef COM_PORT
banner: .asciz "a: disk"
#else
banner: .asciz "Fn: diskn"
#endif
#else
banner: .asciz "NetBSD MBR boot"
#endif
@ -516,6 +585,20 @@ ERR_KEY: .asciz "bad key"
#endif
#endif
#if defined(COM_PORT) && defined(COM_BAUD)
#define COM_DIVISOR (((COM_FREQ / COM_BAUD) + 8) / 16)
com_args:
.byte 0x80 /* divisor latch enable */
.byte +3 /* io_port + 3 */
.byte COM_DIVISOR & 0xff
.byte -3 /* io_port */
.byte COM_DIVISOR >> 8 /* high baud */
.byte +1 /* io_port + 1 */
.byte 0x03 /* 8 bit no parity */
.byte +2 /* io_port + 3 */
num_com_args = (. - com_args)/2
#endif
/*
* I hate #including source files, but the stuff below has to be at
* the correct absolute address.
@ -525,7 +608,26 @@ ERR_KEY: .asciz "bad key"
message_crlf:
call message
movw $crlf, %si
#ifdef COM_PORT
message:
pusha
message_1:
lodsb
test %al, %al
jz 3f
mov COM_PORT_VAL, %dx
outb %al, %dx
add $5, %dl
2: inb %dx
test $0x40, %al
jz 2b
jmp message_1
3: popa
ret
#else
#include <message.S>
#endif
#if 0
#include <dump_eax.S>
#endif
@ -542,7 +644,7 @@ mbr_space = defkey - .
* Default action, as a keyvalue we'd normally read from the BIOS.
*/
defkey:
.byte SCAN_ENTER /* ps/2 code */
.byte KEY_ACTIVE /* ps/2 code */
#ifndef BOOTSEL_FLAGS
#define BOOTSEL_FLAGS 0
#endif
@ -582,4 +684,5 @@ bss_off = 0
bss_start = .
#define BSS(name, size) name = bss_start + bss_off; bss_off = bss_off + size
BSS(ptn_list, 256 * 4) /* long[]: boot sector numbers */
BSS(dump_eax_buff, 16)
BSS(bss_end, 0)

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2008/01/19 21:01:35 dsl Exp $
PROG= mbr_com0
AFLAGS+= -DBOOTSEL -DBOOT_EXTENDED -DCOM_PORT=0
AFLAGS+= -DTERSE_ERROR -DNO_CHS
AFLAGS+= "-DBOOTSEL_FLAGS=MBR_BS_ACTIVE|MBR_BS_EXTLBA|MBR_BS_ASCII"
.include <../Makefile.mbr>

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2008/01/19 21:01:35 dsl Exp $
PROG= mbr_com0_9600
AFLAGS+= -DBOOTSEL -DBOOT_EXTENDED -DCOM_PORT=0 -DCOM_BAUD=9600
AFLAGS+= -DTERSE_ERROR -DNO_CHS
AFLAGS+= "-DBOOTSEL_FLAGS=MBR_BS_ACTIVE|MBR_BS_EXTLBA|MBR_BS_ASCII"
.include <../Makefile.mbr>