138 lines
2.8 KiB
C
138 lines
2.8 KiB
C
/* @(#)bootnd.c 1.1 94/10/31 SMI */
|
|
|
|
/*
|
|
* Boot block for machine with ND in proms. Does tftp to load
|
|
* next stage of boot.
|
|
*/
|
|
#include "../lib/common/saio.h"
|
|
#include <sys/socket.h>
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/if_ether.h>
|
|
#include <netinet/in_systm.h>
|
|
#include <netinet/ip.h>
|
|
#include "../lib/common/sainet.h"
|
|
#include <mon/bootparam.h>
|
|
|
|
#define TIMEOUT 4000 /* retransmission timeout, in milliseconds */
|
|
#define RETRIES 15 /* number of times to retransmit, before giving up */
|
|
#define MAXTIMEOUT 64000 /* max time to wait for reply to broadcast */
|
|
|
|
main()
|
|
{
|
|
struct bootparam *bp;
|
|
struct boottab b;
|
|
static char fname[] = "01234567.SUN2";
|
|
struct sockaddr_in raddr;
|
|
struct ether_addr rether;
|
|
int timeout;
|
|
int eof;
|
|
extern int random;
|
|
extern struct saioreq ether_si;
|
|
extern struct sainet ether_sain;
|
|
extern char recvpacket[];
|
|
|
|
if (romp->v_bootparam == 0) {
|
|
bp = (struct bootparam *)0x2000; /* Old Sun-1 address */
|
|
} else {
|
|
bp = *(romp->v_bootparam); /* S-2: via romvec */
|
|
}
|
|
|
|
/*
|
|
* This is necessary to get the prom ethernet driver to work
|
|
*/
|
|
b = *bp->bp_boottab;
|
|
bp->bp_boottab = &b;
|
|
bp->bp_boottab->b_devinfo = 0;
|
|
|
|
random = *romp->v_nmiclock;
|
|
if (etheropen(bp, ðer_si) < 0) {
|
|
printf("can't open ethernet\n");
|
|
return;
|
|
}
|
|
inet_init(ðer_si, ðer_sain, recvpacket);
|
|
|
|
printf("Using IP Address ");
|
|
printaddr(ether_sain.sain_myaddr);
|
|
|
|
ultox(fname, ether_sain.sain_myaddr.s_addr);
|
|
raddr.sin_addr = ether_sain.sain_hisaddr;
|
|
rether = ether_sain.sain_hisether;
|
|
eof = 0;
|
|
printf("Booting from tftp server at ");
|
|
printaddr(raddr.sin_addr);
|
|
while (! eof && tftpread(raddr, rether, fname, (char *)LOADADDR,
|
|
TIMEOUT, RETRIES) <= 0)
|
|
{
|
|
timeout = TIMEOUT;
|
|
while ((eof = tftpfind(&raddr, &rether, fname,
|
|
(char *)LOADADDR, timeout)) < 0)
|
|
{
|
|
if (timeout < MAXTIMEOUT) {
|
|
timeout *= 2; /* backoff */
|
|
}
|
|
printf("tftp: timeout\n");
|
|
}
|
|
printf("Booting from tftp server at ");
|
|
printaddr(raddr.sin_addr);
|
|
}
|
|
|
|
_exitto(LOADADDR);
|
|
}
|
|
|
|
|
|
/*
|
|
* Print an internet address
|
|
*/
|
|
printaddr(addr)
|
|
struct in_addr addr;
|
|
{
|
|
printf("%d.%d.%d.%d = %x.\n", addr.s_net, addr.s_host, addr.s_lh,
|
|
addr.s_impno, ntohl(addr.s_addr));
|
|
}
|
|
|
|
|
|
/*
|
|
* Unsigned long to hex conversion
|
|
*/
|
|
ultox(buf, val)
|
|
char *buf;
|
|
unsigned long val;
|
|
{
|
|
int i;
|
|
static char hex[] = "0123456789ABCDEF";
|
|
|
|
for (i = 7; i >= 0; i--) {
|
|
buf[i] = hex[val & 0x0f];
|
|
val >>= 4;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Open the ethernet driver in proms
|
|
*/
|
|
etheropen(bp, si)
|
|
struct bootparam *bp;
|
|
struct saioreq *si;
|
|
{
|
|
si->si_boottab = bp->bp_boottab;
|
|
si->si_ctlr = bp->bp_ctlr;
|
|
si->si_unit = bp->bp_unit;
|
|
si->si_boff = bp->bp_part;
|
|
si->si_cc = 0;
|
|
si->si_offset = 0;
|
|
si->si_flgs = 0;
|
|
si->si_devaddr = si->si_devdata = si->si_dmaaddr = 0;
|
|
return((si->si_boottab->b_open)(si));
|
|
}
|
|
|
|
/*
|
|
* Nobody calls this, but must resolve reference in srt0
|
|
*/
|
|
exit()
|
|
{
|
|
_exit();
|
|
}
|
|
|