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

------------------------------------------------------------------------------