141069Swilliam /*-
2*63368Sbostic * Copyright (c) 1990, 1993
3*63368Sbostic * The Regents of the University of California. All rights reserved.
441069Swilliam *
541069Swilliam * This code is derived from software contributed to Berkeley by
641069Swilliam * William Jolitz.
741069Swilliam *
848813Swilliam * %sccs.include.redist.c%
941069Swilliam *
10*63368Sbostic * @(#)bootxx.c 8.1 (Berkeley) 06/11/93
1141069Swilliam */
1241069Swilliam
1356514Sbostic #include <sys/param.h>
1456514Sbostic #include <sys/reboot.h>
1556514Sbostic #include <sys/disklabel.h>
1656514Sbostic
1741069Swilliam #include <a.out.h>
1856514Sbostic #include <stand/saio.h>
1941069Swilliam
2048813Swilliam char *bootprog = "/boot";
2148813Swilliam extern int opendev, bootdev, cyloffset;
2248813Swilliam extern struct disklabel disklabel;
2348813Swilliam
2441069Swilliam /*
2548813Swilliam * Boot program... loads /boot out of filesystem indicated by arguements.
2648813Swilliam * We assume an autoboot unless we detect a misconfiguration.
2741069Swilliam */
2841069Swilliam
main(dev,unit,off)2948813Swilliam main(dev, unit, off)
3041069Swilliam {
3148813Swilliam register struct disklabel *lp;
3248813Swilliam register int io, partition, howto;
3341069Swilliam
3441069Swilliam
3541069Swilliam /* are we a disk, if so look at disklabel and do things */
3648813Swilliam lp = &disklabel;
3748813Swilliam if (lp->d_magic == DISKMAGIC) {
3841069Swilliam /*
3948813Swilliam * Synthesize bootdev from dev, unit, type and partition
4048813Swilliam * information from the block 0 bootstrap.
4148813Swilliam * It's dirty work, but someone's got to do it.
4248813Swilliam * This will be used by the filesystem primatives, and
4348813Swilliam * drivers. Ultimately, opendev will be created corresponding
4448813Swilliam * to which drive to pass to top level bootstrap.
4541069Swilliam */
4641069Swilliam for (io = 0; io < 8; io++)
4748813Swilliam #ifdef notyetSCSI
4848813Swilliam if (lp->d_type == DTYPE_SCSI) {
4948813Swilliam if (lp->d_partitions[io].p_offset == off)
5041069Swilliam break;
5148813Swilliam } else
5248813Swilliam #endif
5348813Swilliam if (lp->d_partitions[io].p_offset == off*lp->d_secpercyl)
5441069Swilliam break;
5548813Swilliam
5648813Swilliam if (io == 8) goto screwed;
5748813Swilliam cyloffset = off;
5848813Swilliam } else {
5948813Swilliam screwed:
6048813Swilliam /* probably a bad or non-existant disklabel */
6148813Swilliam io = 0 ;
6248813Swilliam howto |= RB_SINGLE|RB_ASKNAME ;
6348813Swilliam }
6448813Swilliam
6548813Swilliam /* construct bootdev */
6648813Swilliam /* currently, PC has no way of booting off alternate controllers */
6748813Swilliam bootdev = MAKEBOOTDEV(/*i_dev*/ dev, /*i_adapt*/0, /*i_ctlr*/0,
6848813Swilliam unit, /*i_part*/io);
6948813Swilliam
7041069Swilliam printf("loading %s\n", bootprog);
7141069Swilliam io = open(bootprog, 0);
7241069Swilliam if (io >= 0)
7348813Swilliam copyunix(io, howto);
7441069Swilliam _stop("boot failed\n");
7541069Swilliam }
7641069Swilliam
7741069Swilliam /*ARGSUSED*/
copyunix(io,howto)7848813Swilliam copyunix(io, howto)
7941069Swilliam register io;
8041069Swilliam {
8141069Swilliam struct exec x;
8241069Swilliam register int i;
8341069Swilliam char *addr;
8441069Swilliam
8541069Swilliam i = read(io, (char *)&x, sizeof x);
8641069Swilliam if (i != sizeof x ||
8741069Swilliam (x.a_magic != 0407 && x.a_magic != 0413 && x.a_magic != 0410))
8841069Swilliam _stop("Bad format\n");
8948813Swilliam
9041069Swilliam if ((x.a_magic == 0413 || x.a_magic == 0410) &&
9141069Swilliam lseek(io, 0x400, 0) == -1)
9241069Swilliam goto shread;
9348813Swilliam
9441069Swilliam if (read(io, (char *)0, x.a_text) != x.a_text)
9541069Swilliam goto shread;
9648813Swilliam
9741069Swilliam addr = (char *)x.a_text;
9841069Swilliam if (x.a_magic == 0413 || x.a_magic == 0410)
9941069Swilliam while ((int)addr & CLOFSET)
10041069Swilliam *addr++ = 0;
10148813Swilliam
10241069Swilliam if (read(io, addr, x.a_data) != x.a_data)
10341069Swilliam goto shread;
10448813Swilliam
10541069Swilliam addr += x.a_data;
10641069Swilliam for (i = 0; i < x.a_bss; i++)
10741069Swilliam *addr++ = 0;
10848813Swilliam
10948813Swilliam (*((int (*)()) x.a_entry))(howto, opendev, cyloffset);
11041069Swilliam return;
11141069Swilliam shread:
11241069Swilliam _stop("Short read\n");
11341069Swilliam }
114