Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 08 May 1997 19:40:53 +0900
From:      Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        hackers@freebsd.org, j@uriah.heep.sax.de, yokota@zodiac.mech.utsunomiya-u.ac.jp
Subject:   Re: alternative probe_keyboard.c (was: Re: i386/3124: BOOT_PROBE_KEYBOARD hangs system in bootblocks) 
Message-ID:  <199705081040.TAA00480@zodiac.mech.utsunomiya-u.ac.jp>
In-Reply-To: Your message of "Sat, 26 Apr 1997 03:10:05 %2B1000." <199704251710.DAA05121@godzilla.zeta.org.au> 
References:  <199704251710.DAA05121@godzilla.zeta.org.au> 

next in thread | previous in thread | raw e-mail | index | archive | help
Ooops. I thought I had sent this reply days ago...

Kazu

>There is little need for it in -current.  It could be controlled by an
>option in /boot.config:
>
>-S: force a serial console.  Don't bother probing the keyboard.  To use
>    a keyboard after all, either start booting with a serial console and
>    toggle -S, or if you don't have access to a serial console after all,
>    boot from another disk without -S.  Simplest.
>-K: enable the keyboard probe.  Same as now except there is no danger
>    from buggy keyboard probes except for people who enable the probe.
>    If you use this in a SNAP, don't expect adequate test coverage of
>    the probe :-).
>-D: enable dual normal/serial console.  Do all i/o to both the normal
>    and the serial console without much probing.
>-D -S: as above, except -S just gives preference to the serial console.
>    You can toggle it easily by typing on either console.
>
>I implemented a non-optional ugly version -D.  It's simple except for
>the timeout stuff.  The timeout stuff could be skipped if there were
>a -D flag (users should only use -D if serial hardware exists).  Output
>at 9600 bps is a bit slow to use all the time (twiddle() takes longer
>than disk i/o :-).
>
>Bruce

Based on your code and suggestions, I added some quick hack to your
code (see attached shar file). But I have not tested the code because
we are now hitting the size limit... We need to
reorganize/rearrange the boot code in order to pursue this hack.

Some notes:

* Space problem

We are seriously running out of space in the boot block. Whether we
use the existing probe_keyboard.c or the new one, we cannot turn on
all the options (PROBE_KEYBOARD_LOCK, BOOT_HD_BIAS, NAMEBLOCK,
NAMEBLOCK_WRITEBACK) together with -K -S -D options you have
suggested.

I managed to tweak some bytes and was able to compile the boot block
with PROBE_KEYBOARD_LOCK and BOOT_HD_BIAS. But, enabling NAMEBLOCK
and NAMEBLOCK_WRITEBACK in addition to these will make the boot block
exceed its limit.

* Symbols

RB_DUAL and RB_PROBEKBD are newly defined, temporarily in boot.h.
They should be in sys/reboot.h, but, I wonder if RB_PROBEKBD belongs
there; it might have been better to define it something rather than a
reboot() flag...

* Compile-time options

PROBE_KEYBOARD_LOCK
Same as before. Check if the key lock is on. If it is, the serial
console is forced.

FORCE_COMCONSOLE, PROBE_KEYBOARD
These options are now gone.  probe_keyboard() is always compiled in,
but will be executed only if -K option takes effect (see below).
FORCE_COMCONSOLE is superseded by -S option (see below).

* /boot.config and "Boot:" options

-S
The serial console is forced. The keyboard is not probed.

-D
Console output will go to both the normal and the serial console.  The
keyboard is not probed.

If neither -S nor -D is specified, the systems behaves in the same way
as the current boot block. The normal console is assumed (unless -K
option takes effect, see below).

-K
If neither -S nor -D is specified but -K is specified, the keyboard is
probed and if it is not found, the serial console is assumed. If it is
found, the normal console is assumed.

-D -S
I didn't quite follow your intention and didn't implement this
combination. I have run out of space anyway.

Examples:

-S
The serial console is forced.

-S -K
The serial console is forced. -K is ignored and the keyboard is not
probed.

-K
The keyboard is probed.

-D
Console output will go to both the normal and the serial console.  

-D -S
-D -K
-D -S -K
Console output will go to both the normal and the serial console.  
-S and -K are ignored.

Looking forward to hearing your comments.

Kazu

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	biosboot.diff
#	probe_keyboard.c-echo
#
echo x - biosboot.diff
sed 's/^X//' >biosboot.diff << 'END-of-biosboot.diff'
Xdiff -c2 ../biosboot/boot.c ./boot.c
X*** ../biosboot/boot.c	Thu Apr 10 23:42:23 1997
X--- ./boot.c	Tue Apr 29 10:16:31 1997
X***************
X*** 85,99 ****
X  	int ret;
X  
X! #ifdef PROBE_KEYBOARD
X! 	if (probe_keyboard()) {
X! 		init_serial();
X! 		loadflags |= RB_SERIAL;
X! 		printf("\nNo keyboard found.");
X! 	}
X! #endif
X  
X  #ifdef PROBE_KEYBOARD_LOCK
X  	if (!(inb(0x64) & 0x10)) {
X- 		init_serial();
X  		loadflags |= RB_SERIAL;
X  		printf("\nKeyboard locked.");
X--- 85,92 ----
X  	int ret;
X  
X! 	init_serial();
X  
X  #ifdef PROBE_KEYBOARD_LOCK
X  	if (!(inb(0x64) & 0x10)) {
X  		loadflags |= RB_SERIAL;
X  		printf("\nKeyboard locked.");
X***************
X*** 101,110 ****
X  #endif
X  
X- #ifdef FORCE_COMCONSOLE
X- 	init_serial();
X- 	loadflags |= RB_SERIAL;
X- 	printf("\nSerial console forced.");
X- #endif
X- 
X  	/* Pick up the story from the Bios on geometry of disks */
X  
X--- 94,97 ----
X***************
X*** 156,163 ****
X  #endif	/*NAMEBLOCK*/
X  	readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
X  	if (namebuf[0] != '\0')
X  		printf("boot.config: %s", boot_config);
X  	name = "kernel";
X- 	getbootdev(boot_config, &loadflags);
X  	/*
X  	 * XXX parsing of `name' is in openrd(), so the defaults aren't
X--- 143,150 ----
X  #endif	/*NAMEBLOCK*/
X  	readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
X+ 	getbootdev(boot_config, &loadflags);
X  	if (namebuf[0] != '\0')
X  		printf("boot.config: %s", boot_config);
X  	name = "kernel";
X  	/*
X  	 * XXX parsing of `name' is in openrd(), so the defaults aren't
X***************
X*** 168,172 ****
X  	/* If we have looped, use the previous entries as defaults */
X  	printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
X! 	       "Usage: [[[%d:][%s](%d,a)]%s][-abcCdghrsv]\n"
X  	       "Use 1:sd(0,a)kernel to boot sd0 if it is BIOS drive 1\n"
X  	       "Use ? for file list or press Enter for defaults\n\nBoot: ",
X--- 155,159 ----
X  	/* If we have looped, use the previous entries as defaults */
X  	printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
X! 	       "Usage: [[[%d:][%s](%d,a)]%s][-abcCdDghKrsSv]\n"
X  	       "Use 1:sd(0,a)kernel to boot sd0 if it is BIOS drive 1\n"
X  	       "Use ? for file list or press Enter for defaults\n\nBoot: ",
X***************
X*** 174,183 ****
X  	       dosdev & 0x7f, devs[maj], unit, name);
X  
X! 	loadflags &= RB_SERIAL;	/* clear all, but leave serial console */
X  
X  	/*
X  	 * Be paranoid and make doubly sure that the input buffer is empty.
X  	 */
X! 	if (loadflags & RB_SERIAL)
X  		init_serial();
X  
X--- 161,170 ----
X  	       dosdev & 0x7f, devs[maj], unit, name);
X  
X! 	loadflags &= (RB_SERIAL | RB_DUAL);
X  
X  	/*
X  	 * Be paranoid and make doubly sure that the input buffer is empty.
X  	 */
X! 	if (loadflags & (RB_SERIAL | RB_DUAL))
X  		init_serial();
X  
X***************
X*** 352,355 ****
X--- 339,343 ----
X  getbootdev(char *ptr, int *howto)
X  {
X+ 	int f = *howto;	/* save some bytes */
X  	char c;
X  
X***************
X*** 363,392 ****
X  					goto nextarg;
X  				if (c == 'C')
X! 					*howto |= RB_CDROM;
X  				if (c == 'a')
X! 					*howto |= RB_ASKNAME;
X  				if (c == 'b')
X! 					*howto |= RB_HALT;
X  				if (c == 'c')
X! 					*howto |= RB_CONFIG;
X  				if (c == 'd')
X! 					*howto |= RB_KDB;
X! 				if (c == 'h') {
X! 					*howto ^= RB_SERIAL;
X! 					if (*howto & RB_SERIAL)
X! 						init_serial();
X! 					continue;
X! 				}
X  				if (c == 'g')
X! 					*howto |= RB_GDB;
X  				if (c == 'r')
X! 					*howto |= RB_DFLTROOT;
X  				if (c == 's')
X! 					*howto |= RB_SINGLE;
X  				if (c == 'v')
X! 					*howto |= RB_VERBOSE;
X  			}
X  		if (c == '\0')
X! 			return;
X  		name = ptr;
X  		while (*++ptr != '\0') {
X--- 351,382 ----
X  					goto nextarg;
X  				if (c == 'C')
X! 					f |= RB_CDROM;
X  				if (c == 'a')
X! 					f |= RB_ASKNAME;
X  				if (c == 'b')
X! 					f |= RB_HALT;
X  				if (c == 'c')
X! 					f |= RB_CONFIG;
X  				if (c == 'd')
X! 					f |= RB_KDB;
X! 				if (c == 'h') 
X! 					f ^= RB_SERIAL;
X  				if (c == 'g')
X! 					f |= RB_GDB;
X  				if (c == 'r')
X! 					f |= RB_DFLTROOT;
X  				if (c == 's')
X! 					f |= RB_SINGLE;
X  				if (c == 'v')
X! 					f |= RB_VERBOSE;
X! 				if (c == 'S')
X! 					f |= RB_SERIAL;
X! 				if (c == 'D')
X! 					f |= (RB_DUAL | RB_SERIAL);
X! 				if (c == 'K')
X! 					f |= RB_PROBEKBD;
X  			}
X  		if (c == '\0')
X! 			break;
X  		name = ptr;
X  		while (*++ptr != '\0') {
X***************
X*** 397,399 ****
X--- 387,398 ----
X  		}
X  	}
X+ 
X+ 	if (((f & (RB_SERIAL | RB_DUAL | RB_PROBEKBD)) == RB_PROBEKBD)
X+ 		&& probe_keyboard()) {
X+ 		f |= RB_SERIAL;
X+ 		printf("\nNo keyboard found.");
X+ 	}
X+ 	if (f & (RB_SERIAL | RB_DUAL))
X+ 		init_serial();
X+ 	*howto = f;
X  }
Xdiff -c2 ../biosboot/boot.h ./boot.h
X*** ../biosboot/boot.h	Thu Apr 10 23:42:24 1997
X--- ./boot.h	Mon Apr 28 18:03:51 1997
X***************
X*** 36,39 ****
X--- 36,42 ----
X  #include <ufs/ufs/inode.h>
X  
X+ #define RB_DUAL		0x40000		/* XXX */
X+ #define RB_PROBEKBD	0x80000		/* XXX */
X+ 
X  extern char *devs[];
X  extern char *name;
Xdiff -c2 ../biosboot/io.c ./io.c
X*** ../biosboot/io.c	Thu Apr 10 23:42:24 1997
X--- ./io.c	Mon Apr 28 18:07:45 1997
X***************
X*** 122,132 ****
X  putchar(int c)
X  {
X! 	if (c == '\n') {
X! 		if (loadflags & RB_SERIAL)
X! 			serial_putc('\r');
X! 		else
X! 			putc('\r');
X! 	}
X! 	if (loadflags & RB_SERIAL)
X  		serial_putc(c);
X  	else
X--- 122,131 ----
X  putchar(int c)
X  {
X! 	if (c == '\n') 
X! 		putchar('\r');
X! 	if (loadflags & RB_DUAL) {
X! 		putc(c);
X! 		serial_putc(c);
X! 	} else if (loadflags & RB_SERIAL)
X  		serial_putc(c);
X  	else
X***************
X*** 140,144 ****
X  
X  loop:
X! 	if ((c = ((loadflags & RB_SERIAL) ? serial_getc() : getc())) == '\r')
X  		c = '\n';
X  	if (c == '\b') {
X--- 139,155 ----
X  
X  loop:
X! 	if (loadflags & RB_DUAL) {
X! 		if (ischar())
X! 			c = getc();
X! 		else if (serial_ischar())
X! 			c = serial_getc();
X! 		else
X! 			goto loop;
X! 	} else if (loadflags & RB_SERIAL) {
X! 		c = serial_getc();
X! 	} else {
X! 		c = getc();
X! 	}
X! 	if (c == '\r')
X  		c = '\n';
X  	if (c == '\b') {
X***************
X*** 154,158 ****
X  }
X  
X- #ifdef PROBE_KEYBOARD
X  /*
X   * This routine uses an inb to an unused port, the time to execute that
X--- 165,168 ----
X***************
X*** 172,176 ****
X  		(void)inb(0x84);
X  }
X- #endif /* PROBE_KEYBOARD */
X  
X  static __inline int
X--- 182,185 ----
X***************
X*** 186,191 ****
X  	isc = ischar();
X  
X! 	if (!(loadflags & RB_SERIAL))
X  		return (isc);
X  	return (serial_ischar());
X  
X--- 195,204 ----
X  	isc = ischar();
X  
X! 	if (loadflags & RB_DUAL) {
X! 		if (isc != 0)
X! 			return (isc);
X! 	} else if (!(loadflags & RB_SERIAL)) {
X  		return (isc);
X+ 	}
X  	return (serial_ischar());
X  
Xdiff -c2 ../biosboot/serial.S ./serial.S
X*** ../biosboot/serial.S	Thu Apr 10 23:42:24 1997
X--- ./serial.S	Mon Apr 28 11:25:35 1997
X***************
X*** 96,101 ****
X  	push	%edx
X  
X  	mov	$COMCONSOLE + 5, %edx	# line status reg
X! 1:	inb	%dx, %al
X  	test	$0x20, %al
X  	jz	1b		# TX buffer not empty
X--- 96,105 ----
X  	push	%edx
X  
X+ 	movl	$10000, %ecx	# timeout
X  	mov	$COMCONSOLE + 5, %edx	# line status reg
X! 1:
X! 	decl	%ecx
X! 	je	2f
X! 	inb	%dx, %al
X  	test	$0x20, %al
X  	jz	1b		# TX buffer not empty
X***************
X*** 106,109 ****
X--- 110,114 ----
X  	outb	%al, %dx	# send this one
X  
X+ 2:
X  	pop	%edx
X  	pop	%ebp
X***************
X*** 177,181 ****
X  	outb	%al, %dx
X  
X! 	add	$2, %edx	# line control reg
X  	movb	$0x13, %al
X  	outb	%al, %dx	# 8 bit, no parity, 1 stop bit
X--- 182,190 ----
X  	outb	%al, %dx
X  
X! 	incl	%edx		# fifo control register (if any)
X! 	xorl	%eax,%eax
X! 	outb	%al, %dx	# disable fifo to reduce worst-case busy-wait
X! 
X! 	incl	%edx		# line control reg
X  	movb	$0x13, %al
X  	outb	%al, %dx	# 8 bit, no parity, 1 stop bit
END-of-biosboot.diff
echo x - probe_keyboard.c-echo
sed 's/^X//' >probe_keyboard.c-echo << 'END-of-probe_keyboard.c-echo'
X/*-
X * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $Id:$
X */
X
X#include <i386/include/cpufunc.h>
X#include <i386/isa/isa.h>
X#include <i386/isa/ic/i8042.h>
X#include <i386/isa/kbdio.h>
X
X#include "boot.h"
X
X#define PROBE_MAXRETRY	5
X#define PROBE_MAXWAIT	400
X
X#define IO_DUMMY	0x84
X
X/* 7 microsec delay necessary for some keyboard controllers */
Xstatic void
Xdelay7(void)
X{
X    /* 
X     * I know this is broken, but no timer is avaiable yet at this stage...
X     * See also comments in `delay1ms()' in `io.c'.
X     */
X    inb(IO_DUMMY); inb(IO_DUMMY);
X    inb(IO_DUMMY); inb(IO_DUMMY);
X    inb(IO_DUMMY); inb(IO_DUMMY);
X}
X
X/* 
X * Perform a simple test on the keyboard; issue the ECHO command and see
X * if the right answer is returned. We don't do anything as drastic as
X * full keyboard reset; it will be too troublesome and take too much time.
X */
Xint
Xprobe_keyboard(void)
X{
X    int retry = PROBE_MAXRETRY;
X    int wait;
X    int i;
X
X    while (--retry >= 0) {
X	/* flush any noise */
X	while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
X	    delay7();
X	    inb(IO_KBD + KBD_DATA_PORT);
X	    delay1ms();
X	}
X
X	/* wait until the controller can accept a command */
X	for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
X	    if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 
X                & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
X		break;
X	    if (i & KBDS_ANY_BUFFER_FULL) {
X		delay7();
X	        inb(IO_KBD + KBD_DATA_PORT);
X	    }
X	    delay1ms();
X	}
X	if (wait <= 0)
X	    continue;
X
X	/* send the ECHO command */
X	outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
X
X	/* wait for a response */
X	for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
X	     if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
X		 break;
X	     delay1ms();
X	}
X	if (wait <= 0)
X	    continue;
X
X	delay7();
X	i = inb(IO_KBD + KBD_DATA_PORT);
X#ifdef PROBE_KBD_BEBUG
X        printf("probe_keyboard: got 0x%x.\n", i);
X#endif
X	if (i == KBD_ECHO) {
X	    /* got the right answer */
X	    return (0);
X	}
X    }
X
X    return (1);
X}
X
END-of-probe_keyboard.c-echo
exit






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705081040.TAA00480>