1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-16 10:20:30 +00:00

Submitted by: Bill Paul (wpaul@ctr.columbia.edu)

Obtained from:
bios boot block changed to allow booting from both the attached graphics
display and from a serial port. (A specially compiled serial boot block
is no longer necessary.) The boot block should detect the presence or
absence of a keyboard: if there is no keyboard, COM1 is turned into the
console. This simulates the behavior of the Sun boot PROMs. Unplug your
keyboard, attach a terminal to COM1 and you should be ready to go. :)
This commit is contained in:
Bill Paul 1995-01-20 07:48:27 +00:00
parent 2b237b4058
commit f778c9da00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=5745
6 changed files with 473 additions and 55 deletions

View File

@ -1,15 +1,16 @@
# $Id: Makefile,v 1.22 1994/11/05 21:06:16 ache Exp $
# $Id: Makefile,v 1.23 1994/12/18 19:14:08 bde Exp $
#
PROG= boot
# Order is very important on the SRCS line for this prog
SRCS= start.S table.c boot2.S boot.c asm.S bios.S io.c disk.c sys.c
SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S
SRCS+= probe_keyboard.c io.c disk.c sys.c
BINDIR= /usr/mdec
BINMODE= 444
CFLAGS= -O -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT}
CFLAGS= -O2 -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT} -DCOMCONSOLE=0x3F8
CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK}
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../..
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../.. -DRB_SERIAL=0x1000
CLEANFILES+= boot.nohdr boot.strip boot1 boot2
DPADD= ${LIBC}
LDFLAGS+= -N -T 0 -nostdlib

View File

@ -0,0 +1,132 @@
$Id$
SERIAL CONSOLE USAGE NOTES
Bill Paul (wpaul@ctr.columbia.edu)
The FreeBSD boot block can now be used to boot FreeBSD on a system with
only a dumb terminal on a serial port (COM1) as a console. This feature
is provided for the benefit of people who wish to install FreeBSD on
dedicated file/compute/terminal server machines that have no keyboard
(or monitor) attached, just as is possible with Sun workstations and
servers. People who don't need this extra functionality shouldn't notice
the changes at all (unless I've screwed something up horribly).
Note that 'options COMCONSOLE' can still be used to force the kernel to
boot in 'serial console' mode regardless of what boot options you use.
To boot FreeBSD in serial console mode, you must to the following:
- Unplug your keyboard. Most PC systems probe for the keyboard during the
Power-On Self-Test (POST) and will generate an error if the keyboard
isn't detected. Additionally, many machines will pause the boot process
and wait for you to reattach the keyboard and press a key before
proceeding any further. If your computer complains about the lack of a
keyboard but boots anyway, then you don't have to do anything special.
(One machine with a PHOENIX BIOS that I have here merely says 'Keyboard
failed' then continues to boot normally.) If your machine complains
loudly about the lack of a keyboard and won't continue to boot until you
plug it back in, you'll have to go into your CMOS configuration menu and
change the 'Keyboard' setting to 'Not installed' in order to bypass the
keyboard probe.
NOTE: Setting the keyboard to 'Not installed' in the CMOS configuration
does *NOT* mean that you won't be able to use your keyboard. All this
does is tell the BIOS not to probe for a keyboard at power-on so that
it won't bitch and moan if the keyboard isn't plugged in. You can leave the
keyboard plugged in even with this flag set to 'Not installed' and the
keyboard will still work. I repeat: changing the CMOS 'keyboard' setting
to 'Not installed' only disables the BIOS's keyboard probe; it does
*NOT* actually disable the keyboard.
- Plug a dumb terminal into COM1. If you don't have a dumb terminal, you
can use an old PC/XT with a modem program, or the serial port on
another UNIX box. If you don't have a COM1, get one. At this time,
there is no way to select a port other than COM1 without recompiling
both the kernel and the boot blocks. If you're already using COM1 for
another device, you'll have to temporarily remove that device and
install a new boot block and kernel once you get FreeBSD up and running.
(It is assumed that COM1 will be available on a file/compute/terminal
server anyway; if you really need COM1 for something else (and you can't
switch it to COM2), then you probably shouldn't even be bothering with
all this.)
The serial port settings are hardcoded to 9600 baud, 8 bits, no parity,
1 stop bit.
NOTE: in addition to a serial cable, you will need a null modem adapter
in order to connect the terminal to the PC's serial port. If you don't
have one, go to Radio Shack and buy one: they're cheap.
- Boot the machine. The boot block will probe for a keyboard on your
system. If it fails to find one, you'll see a prompt appear on the
terminal that looks like this:
No keyboard found.
>> FreeBSD BOOT @ 0x10000: 640/7168 k of memory
Use hd(1,a)/kernel to boot sd0 when wd0 is also installed.
Usage: [[[fd(0,a)]/kernel][-s][-r][-a][-c][-d][-b][-v][-h]]
Use ? for file list or simply press Return for defaults
Boot:
This is identical to the prompt that normally appears on the VGA console,
except for the 'No keyboard found' message that indicates a keyboard
couldn't be detected. (If a keyboard is detected, the boot prompt will
appear on the VGA display as usual.)
From here you can boot the system (or let it autoboot by itself) just
like you can from the VGA console and the kernel will automatically
use COM1 as the console device. No recompilation or 'options COMCONSOLE'
is required. This is done by passing a special flag to the kernel in
the 'boothowto' word. (The curious can refer to <sys/reboot.h> and the
sio driver sources for details.)
- You will notice that there's a new boot flag: -h. You can use this to
force the kernel to switch console devices. For instance, if you boot
from the VGA console, you can use -h to force the kernel to use the
serial port as its console device. Alternatively, if you boot from
the serial port, using -h will force the kernel to use the VGA display
as the console instead. (Can you say 'toggle' boys and girls? I knew
you could. Now try saying 'XOR.')
CAVEATS:
- The idea here is to allow people to set up dedicated servers that require
no graphics hardware or attached keyboards. Unfortunately, while (most?)
every system will let you boot without a keyboard, there are quite a few
that will not let you boot without a graphics adapter. Machines with
AMI BIOSes can be configured to boot with no graphics adapter installed
simply by changing the 'graphics adapter' setting in the CMOS configuration
to 'Not installed.' However, many machines do not support this option
and will refuse to boot if you have no display hardware installed. With
these machines, you'll have to leave some kind of graphics card installed,
(even if it's just a junky mono board) although you won't have to plug a
monitor into it. You might also try installing an AMI BIOS. :)
- Using a port other than COM1 as the console requires some recompiling.
Again, it's usually assumed that COM1 will be available for use as a
console device on a dedicated file/compute/terminal server, so hopefully
you'll never have to do this. But if you feel you must change the console
to a different port, here's how:
o Get the kerndist kernel source package.
o Edit /sys/i386/boot/biosboot/Makefile and set COMCONSOLE to the
address of the port you want to use (0x3F8, 0x2E8, 0x3E8 or
0x2E8). Only COM1 through COM4 can be used; multiport serial
cards will not work. No interrupt setting is needed.
o Create a custom kernel configuration file and add the following
lines:
options "CONADDR=0x3F8"
options "CONUNIT=0"
Set CONADDR to the same address that you selected for COMCONSOLE
in the bootbios Makefile. Set CONUNIT to the unit number of the
serial port that this address corresponds to (0 = sio0, 1 = sio1,
etc). This implies that the serial port you want to use must be
configured into the kernel in the normal way first. I'm not
going to list all the possible combinations here; just use your
head and you should be okay.
o Recompile both the boot blocks and the kernel.
o Install the boot blocks with the disklabel command and boot
from the new kernel.

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, [92/04/03 16:51:14 rvb]
* $Id: boot.c,v 1.28 1994/12/18 19:14:13 bde Exp $
* $Id: boot.c,v 1.29 1994/12/18 20:30:10 joerg Exp $
*/
@ -59,52 +59,47 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
struct exec head;
struct bootinfo_t bootinfo;
char *name;
char *names[] = {
"/kernel"
};
#define NUMNAMES (sizeof(names)/sizeof(char *))
char *name = { "/kernel" };
#ifdef COMCONSOLE
extern void init_serial(void);
#endif
extern int probe_keyboard(void);
int loadflags = 0;
extern int end;
boot(drive)
int drive;
{
int loadflags, currname = 0, ret;
int ret;
char *t;
#ifdef COMCONSOLE
init_serial();
#endif
if (probe_keyboard()) {
init_serial();
loadflags |= RB_SERIAL;
printf ("\nNo keyboard found.\n");
}
/* Pick up the story from the Bios on geometry of disks */
for(ret = 0; ret < N_BIOS_GEOM; ret ++)
bootinfo.bios_geom[ret] = get_diskinfo(ret + 0x80);
printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n",
ouraddr, memsize(0), memsize(1));
printf("Use hd(1,a)/kernel to boot sd0 when wd0 is also installed.\n");
printf("Usage: [[[%s(0,a)]%s][-s][-r][-a][-c][-d][-b][-v]]\n",
devs[(drive & 0x80) ? 0 : 2], names[0]);
printf("Use ? for file list or simply press Return for defaults\n");
/* This is nasty, but why use 4 printf()s when 1 will do. */
printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\nUse hd(1,a)/kernel to boot sd0 when wd0 is also installed.\nUsage: [[[%s(%d,a)]%s][-s][-r][-a][-c][-d][-b][-v][-h]]\nUse ? for file list or simply press Return for defaults\n", ouraddr, memsize(0), memsize(1), devs[(drive & 0x80) ? 0 : 2],
(unit = (drive & 0x7f)), name);
gateA20();
loadstart:
/***************************************************************\
* As a default set it to the first partition of the first *
* floppy or hard drive *
\***************************************************************/
part = unit = 0;
maj = (drive&0x80 ? 0 : 2); /* a good first bet */
name = names[currname++];
loadflags = 0;
if (currname == NUMNAMES)
currname = 0;
printf("Boot: ");
part = 0;
maj = (drive&0x80 ? 0 : 2); /* a good first bet */
printf ("Boot: ");
getbootdev(&loadflags);
ret = openrd();
if (ret != 0) {
@ -147,6 +142,12 @@ loadprog(howto)
, 'a'+part
, name
, addr);
/*
* With the current scheme of things, addr can never be less than ouraddr,
* so this next bit of code is largely irrelevant. Taking it out saves lots
* of space.
*/
#ifdef REDUNDANT
if(addr < ouraddr)
{
if((addr + head.a_text + head.a_data) > ouraddr)
@ -160,6 +161,7 @@ loadprog(howto)
return;
}
}
#endif
printf("text=0x%x ", head.a_text);
/********************************************************/
/* LOAD THE TEXT SEGMENT */
@ -185,6 +187,11 @@ loadprog(howto)
/* (but clear it) */
/********************************************************/
printf("bss=0x%x ", head.a_bss);
/*
* This doesn't do us any good anymore either.
*/
#ifdef REDUNDANT
if( (addr < ouraddr) && ((addr + head.a_bss) > ouraddr))
{
pbzero(addr,ouraddr - (int)addr);
@ -194,7 +201,9 @@ loadprog(howto)
pbzero(addr,head.a_bss);
}
addr += head.a_bss;
#else
pbzero(addr,head.a_bss);
#endif
#ifdef LOADSYMS /* not yet, haven't worked this out yet */
if (addr > 0x100000)
{
@ -286,6 +295,8 @@ getbootdev(howto)
*howto |= RB_HALT; continue;
case 'v':
*howto |= RB_VERBOSE; continue;
case 'h':
*howto ^= RB_SERIAL; continue;
}
else {
name = ptr;

View File

@ -1,4 +1,3 @@
/*
* Mach Operating System
* Copyright (c) 1992, 1991 Carnegie Mellon University
@ -25,10 +24,11 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:35:57 rpd
* $Id: io.c,v 1.9 1994/09/20 22:24:59 adam Exp $
* $Id: io.c,v 1.10 1994/11/07 11:26:29 davidg Exp $
*/
#include <machine/cpufunc.h>
#include <sys/reboot.h>
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
@ -44,6 +44,8 @@
enable data line
enable clock line */
extern int loadflags;
/*
* Gate A20 for high memory
*/
@ -73,7 +75,6 @@ printf(format,data)
int *dataptr = &data;
char c;
reset_twiddle();
while (c = *format++)
if (c != '%')
putchar(c);
@ -119,9 +120,12 @@ printf(format,data)
putchar(c)
{
if (c == '\n')
putc('\r');
putc(c);
if (c == '\n') {
if (loadflags & RB_SERIAL) serial_putc('\r');
else putc('\r');
}
if (loadflags & RB_SERIAL) serial_putc(c);
else putc(c);
}
getchar(in_buf)
@ -130,7 +134,7 @@ getchar(in_buf)
int c;
loop:
if ((c=getc()) == '\r')
if ((c = ((loadflags & RB_SERIAL) ? serial_getc(c) : getc(c))) == '\r')
c = '\n';
if (c == '\b') {
if (in_buf != 0) {
@ -173,7 +177,7 @@ char *buf;
#if BOOTWAIT
for (i = BOOTWAIT; i>0; delay1ms(),i--)
#endif
if (ischar())
if ((loadflags & RB_SERIAL) ? serial_ischar() : ischar())
for (;;)
switch(*ptr = getchar(ptr - buf) & 0xff) {
case '\n':
@ -186,6 +190,7 @@ char *buf;
default:
ptr++;
}
return 0;
}
@ -208,24 +213,13 @@ int len;
*to++ = *from++;
}
static int tw_on;
static int tw_pos;
static char tw_chars[] = "|/-\\";
/* To quote Ken: "You are not expected to understand this." :) */
reset_twiddle()
{
if (tw_on)
putchar('\b');
tw_on = 0;
tw_pos = 0;
}
static unsigned long tw_chars = 0x5C2D2F7C; /* "\-/|" */
twiddle()
{
if (tw_on)
putchar('\b');
else
tw_on = 1;
putchar(tw_chars[tw_pos++]);
tw_pos %= (sizeof(tw_chars) - 1);
putchar((char)tw_chars);
tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);
putchar('\b');
}

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 1992-1995 Søren Schmidt
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This is a modified version of the keyboard reset code used in syscons.
* If the keyboard reset fails, we assume that the keyboard has been
* unplugged and we use a serial port (COM1) as the console instead.
* Returns 1 on failure (no keyboard), 0 on success (keyboard attached).
*
* This grody hack brought to you by Bill Paul (wpaul@ctr.columbia.edu)
*
* $Id$
*/
#include <machine/console.h>
#include <machine/cpufunc.h>
#ifdef BOOTWAIT
extern int delay1ms(void);
#else
int delay1ms()
{
int i = 800;
while (--i >= 0)
(void)inb(0x84);
}
#endif
int
probe_keyboard(void)
{
int i, retries = 5;
unsigned char val;
/* Try to reset keyboard hardware */
while (retries--) {
outb(KB_DATA, KB_RESET);
for (i=0; i<100000; i++) {
delay1ms();
val = inb(KB_DATA);
if (val == KB_ACK || val == KB_ECHO)
return(0);
if (val == KB_RESEND)
return (1);
}
}
return (0);
}

View File

@ -0,0 +1,198 @@
/*
* Mach Operating System
* Copyright (c) 1992, 1991 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:34:26 rpd
* $Id: bios.S,v 1.1 1994/12/18 20:12:08 joerg Exp $
*/
/*
Copyright 1988, 1989, 1990, 1991, 1992
by Intel Corporation, Santa Clara, California.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appears in all
copies and that both the copyright notice and this permission notice
appear in supporting documentation, and that the name of Intel
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Serial bootblock interface routines
* Copyright (c) 1994, J"org Wunsch
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
.file "serial.s"
#include "asm.h"
.text
/*
* The serial port interface routines implement a simple polled i/o
* interface to a standard serial port. Due to the space restrictions
* for the boot blocks, no BIOS support is used (since BIOS requires
* expensive real/protected mode switches), instead the rudimentary
* BIOS support is duplicated here.
*
* The base address for the i/o port is passed from the Makefile in
* the COMCONSOLE preprocessor macro. Console parameters are currently
* hard-coded to 9600 Bd, 8 bit. This can be changed in the
* init_serial() function.
*/
/*
* void serial_putc(char ch)
* send ch to serial port
*
*/
ENTRY(serial_putc)
push %ebp
mov %esp, %ebp
push %edx
mov $COMCONSOLE + 5, %edx # line status reg
1: inb %dx, %al
test $0x20, %al
jz 1b # TX buffer not empty
movb 0x8(%ebp), %al
sub $5, %edx # TX output reg
outb %al, %dx # send this one
pop %edx
pop %ebp
ret
/*
* int serial_getc(void)
* read a character from serial port
*/
ENTRY(serial_getc)
push %ebp
mov %esp, %ebp
push %edx
mov $COMCONSOLE + 5, %edx # line status reg
1:
inb %dx, %al
testb $0x01, %al
jz 1b # no RX char available
xor %eax, %eax
sub $5, %edx # RX buffer reg
inb %dx, %al # fetch (first) character
cmp $0x7F, %eax # make DEL...
jne 2f
mov $0x08, %eax # look like BS
2:
pop %edx
pop %ebp
ret
/*
* int serial_ischar(void)
* if there is a character pending, return true; otherwise return 0
*/
ENTRY(serial_ischar)
push %ebp
mov %esp, %ebp
push %edx
xorl %eax, %eax
mov $COMCONSOLE + 5, %edx # line status reg
inb %dx, %al
andb $0x01, %al # RX char available?
pop %edx
pop %ebp
ret
/*
* void init_serial(void)
* initialize the serial console port to 9600 Bd, 8 bpc
*/
ENTRY(init_serial)
push %ebp
mov %esp, %ebp
push %edx
mov $COMCONSOLE + 3, %edx # line control reg
movb $0x80, %al
outb %al, %dx # enable DLAB
sub $3, %edx # divisor latch, low byte
mov $12, %ax # divisor 12: 9600 Bd
outb %al, %dx
inc %edx # divisor latch, high byte
movb %ah, %al
outb %al, %dx
add $2, %edx # line control reg
movb $0x13, %al
outb %al, %dx # 8 bit, no parity, 1 stop bit
inc %edx # modem control reg
mov $3, %al
outb %al, %dx # enable DTR/RTS
/* now finally, flush the input buffer */
inc %edx # line status reg
1:
inb %dx, %al
testb $0x01, %al
jz 2f # no more characters buffered
sub $5, %edx # rx buffer reg
inb %dx, %al # throw away
add $5, %edx
jmp 1b
2:
pop %edx
pop %ebp
ret