Subject: release
To: None <glass@sun-lamp.cs.berkeley.edu>
From: Gordon W. Ross <gwr@jericho.mc.com>
List: port-sun3
Date: 02/07/1994 19:16:40
I haven't tried booting the kernel yet, but I have played with
netboot a little. I have a stand-alone program that reads
commands and prints output using the PROM services. Perhaps
this could be used to ask some questions during kernel startup
(i.e boot -a) instead of the nasty compiled-in NFS config.
One concern though: How can I wean my code from its dependence
on the SunOS header file <mon/sunromvec.h> without violating
Sun's copyright? That header defines the interface to the PROM
services. One is allowed to define compatible interfaces, right?
There are many useful services in the boot PROM! (device i/o ...)
Anyway, in case anyone can use some of these functions, I have
appended my current toy stand-alone program below. I test it
by copying it to tape followed by halt, "b st()" ...
I think I may try to get netboot working based on this.
Enjoy,
Gordon W. Ross Mercury Computer Systems
gwr@mc.com 199 Riverneck Road
508-256-1300 Chelmsford, MA 01824-2820
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Makefile
# boot.c
# misc.c
# romsvc.c
# start.s
# This archive created: Mon Feb 7 19:12:46 1994
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# These are determined by the PROM loader.
# (See SunOS <mon/bootparam.h>
LOADADDR= 4000 # before self relocation
LINKADDR=240000 # after self relocation
CFLAGS= -fsoft
OBJS = start.o boot.o misc.o romsvc.o
boot : $(OBJS)
ld -o $@ -N -T $(LINKADDR) $(OBJS)
tape: boot
dd if=boot ibs=32 skip=1 | \
dd of=/dev/rst0 conv=sync
ALLFILES = Makefile boot.c misc.c romsvc.c start.s
shar.out : $(ALLFILES)
shar $(ALLFILES) > $@
SHAR_EOF
fi # end of overwriting check
if test -f 'boot.c'
then
echo shar: will not over-write existing file "'boot.c'"
else
cat << \SHAR_EOF > 'boot.c'
/* boot.c - example boot program */
#include <mon/sunromvec.h>
extern char *gets();
static char linebuf[64];
main()
{
int c, n;
char *p;
for(;;) {
printf("? ");
p = gets(linebuf);
if (!strcmp(p, "q"))
break;
if (!strcmp(p, "t")) {
n = gettenths();
printf("ticks=%d\n", n);
}
if (!strcmp(p, "p"))
prBootParams();
}
printf("returning to monitor...\n");
}
prBootParams()
{
struct bootparam *bp;
int i;
bp = *romp->v_bootparam;
printf("dev: %s(%d,%d,%d)\n",
bp->bp_dev,
bp->bp_ctlr,
bp->bp_unit,
bp->bp_part);
printf("file: %s args:", bp->bp_name);
for (i=0; i < 8; i++) {
if (bp->bp_argv[i] == 0)
break;
printf(" %s", bp->bp_argv[i]);
}
printf("\n");
}
SHAR_EOF
fi # end of overwriting check
if test -f 'misc.c'
then
echo shar: will not over-write existing file "'misc.c'"
else
cat << \SHAR_EOF > 'misc.c'
/* misc.c - library functions */
#include <sys/types.h>
char *
gets(s)
char *s;
{
int c;
char *p;
p = s;
while ((c = getchar()) != '\n')
*p++ = c;
*p = '\0';
return s;
}
void
panic(fmt, a1,a2,a3,a4,a5)
char *fmt;
int a1,a2,a3,a4,a5;
{
printf("\npanic: ");
printf(fmt, a1,a2,a3,a4,a5);
exit();
}
strcmp(s1, s2)
char *s1, *s2;
{
while (*s1 && (*s1 == *s2)) {
s1++;
s2++;
}
return (*s2 - *s1);
}
extern long getmstimer();
u_long
gettenths()
{
return (u_long)(getmstimer() / 100);
}
time_t
getsecs()
{
return (time_t)(getmstimer() / 1000);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'romsvc.c'
then
echo shar: will not over-write existing file "'romsvc.c'"
else
cat << \SHAR_EOF > 'romsvc.c'
/* romsvc.c - ROM Services (C wrappers) */
#include <mon/sunromvec.h>
/* Raw get char (returns each key immediately). */
int
rawgetchar()
{
return (*romp->v_getchar)();
}
/* Raw put char (immediate print) */
void
rawputchar(c)
int c;
{
(*romp->v_putchar)(c);
}
/* Raw get char, non-block (returns -1 when no input) */
int
rawgetchNB()
{
return (*romp->v_mayget)();
}
/* Line-mode getchar */
int
getchar()
{
int c;
static int haveline;
if (!haveline) {
haveline = 1;
(*romp->v_getline)();
}
c = (*romp->v_getone)();
/* getone returns zero at end of line */
if (c == 0) {
haveline = 0;
c = '\n';
}
return c;
}
/* The PROM handles only 5 args after the format string. */
void
printf(fmt, a1,a2,a3,a4,a5)
char *fmt;
int a1,a2,a3,a4,a5;
{
(*romp->v_printf)(fmt,a1,a2,a3,a4,a5);
}
void
reboot(s)
char *s; /* boot string, i.e. "sd()vmunix" */
{
(*romp->v_boot_me)(s);
}
/* This returns the current value of a millisecond timer. */
int
getmstimer()
{
return *romp->v_nmiclock;
}
/* Exit to monitor. Never returns. */
void
exit()
{
(*romp->v_exit_to_mon)();
}
/* XXX - What does this do? Is it useful? */
setcxsegmap(a1, a2, a3, a4)
int a1, a2, a3, a4;
{
(*romp->v_setcxsegmap)(a1, a2, a3, a4);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'start.s'
then
echo shar: will not over-write existing file "'start.s'"
else
cat << \SHAR_EOF > 'start.s'
| start.s - for stand-alone programs
ROMVEC = 0x0FEF0000 | This value is Sun3 specific.
.text
.globl _start
_start:
| Check to see if the code is located correctly.
lea _start, a0 | current location (0x4000)
lea _start:l, a1 | desired location (LINKADDR)
cmpl a0, a1
beqs Lcpdone
| Relocate the code and data to where they belong.
lea _edata:l, a2 | end of dest region
Lcp:
movl a0@+, a1@+
cmpl a2, a1
ble Lcp
| Jump to the relocated code
lea Lcpdone:l, a0
jmp a0@
Lcpdone:
| now in the relocated code
| Clear BSS
lea _edata:l, a0
lea _end:l, a2 | end of dest region
Lclr:
clrl a0@+
cmpl a2, a0
ble Lclr
| Set up stack (just before text)
lea _start:l, a0
movl a0, sp
| Call main(0, 0)
clrl sp@-
clrl sp@-
jsr _main:l
addqw #8, sp
jsr _exit:l
| If exit returns, fall into reset.
| Jump to the PROM reset entry point.
.globl _reset
_reset:
movw #0x2700, sr | supervisor mode, spl 7
lea ROMVEC:l, a0
movl a0@, sp | initial sp
movl a0@(4), a1 | initial pc
jmp a1@
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
------------------------------------------------------------------------------