141488Smckusick /*
2*63825Sbostic * Copyright (c) 1990, 1993
3*63825Sbostic * The Regents of the University of California. All rights reserved.
441488Smckusick *
541488Smckusick * %sccs.include.redist.c%
641488Smckusick *
7*63825Sbostic * @(#)mkboot.c 8.1 (Berkeley) 07/15/93
841488Smckusick */
941488Smckusick
1041488Smckusick #ifndef lint
1163811Shibler static char copyright[] =
1263811Shibler "@(#) Copyright (c) 1990, 1993\n\
1363811Shibler The Regents of the University of California. All rights reserved.\n";
1441488Smckusick #endif /* not lint */
1541488Smckusick
1641488Smckusick #ifndef lint
1745790Sbostic static char sccsid[] = "@(#)mkboot.c 7.2 (Berkeley) 12/16/90";
1841488Smckusick #endif /* not lint */
1941488Smckusick
2056510Sbostic #include <sys/param.h>
2156510Sbostic #include <sys/exec.h>
2256510Sbostic #include <sys/file.h>
2354073Shibler
2456510Sbostic #include <hp300/stand/volhdr.h>
2556510Sbostic
2641488Smckusick #include <stdio.h>
2741488Smckusick #include <ctype.h>
2841488Smckusick
2957299Shibler #define LIF_NUMDIR 8
3057299Shibler
3157299Shibler #define LIF_VOLSTART 0
3257299Shibler #define LIF_VOLSIZE sizeof(struct lifvol)
3357299Shibler #define LIF_DIRSTART 512
3457299Shibler #define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir))
3557299Shibler #define LIF_FILESTART 8192
3657299Shibler
3757299Shibler #define btolifs(b) (((b) + (SECTSIZE - 1)) / SECTSIZE)
3857299Shibler #define lifstob(s) ((s) * SECTSIZE)
3957299Shibler
4041488Smckusick int lpflag;
4141488Smckusick int loadpoint;
4241488Smckusick struct load ld;
4341488Smckusick struct lifvol lifv;
4457299Shibler struct lifdir lifd[LIF_NUMDIR];
4541488Smckusick struct exec ex;
4641488Smckusick char buf[10240];
4741488Smckusick
4857299Shibler /*
4957299Shibler * Old Format:
5057299Shibler * sector 0: LIF volume header (40 bytes)
5157299Shibler * sector 1: <unused>
5257299Shibler * sector 2: LIF directory (8 x 32 == 256 bytes)
5357299Shibler * sector 3-: LIF file 0, LIF file 1, etc.
5457299Shibler * where sectors are 256 bytes.
5557299Shibler *
5657299Shibler * New Format:
5757299Shibler * sector 0: LIF volume header (40 bytes)
5857299Shibler * sector 1: <unused>
5957299Shibler * sector 2: LIF directory (8 x 32 == 256 bytes)
6057299Shibler * sector 3: <unused>
6157299Shibler * sector 4-31: disklabel (~300 bytes right now)
6257299Shibler * sector 32-: LIF file 0, LIF file 1, etc.
6357299Shibler */
main(argc,argv)6441488Smckusick main(argc, argv)
6541488Smckusick char **argv;
6641488Smckusick {
6741488Smckusick int ac;
6841488Smckusick char **av;
6963811Shibler int from1, from2, from3, to;
7041488Smckusick register int n;
7163811Shibler char *n1, *n2, *n3, *lifname();
7241488Smckusick
7341488Smckusick ac = --argc;
7441488Smckusick av = ++argv;
7541488Smckusick if (ac == 0)
7641488Smckusick usage();
7741488Smckusick if (!strcmp(av[0], "-l")) {
7841488Smckusick av++;
7941488Smckusick ac--;
8041488Smckusick if (ac == 0)
8141488Smckusick usage();
8241488Smckusick sscanf(av[0], "0x%x", &loadpoint);
8341488Smckusick lpflag++;
8441488Smckusick av++;
8541488Smckusick ac--;
8641488Smckusick }
8741488Smckusick if (ac == 0)
8841488Smckusick usage();
8941488Smckusick from1 = open(av[0], O_RDONLY, 0);
9041488Smckusick if (from1 < 0) {
9141488Smckusick perror("open");
9241488Smckusick exit(1);
9341488Smckusick }
9441488Smckusick n1 = av[0];
9541488Smckusick av++;
9641488Smckusick ac--;
9741488Smckusick if (ac == 0)
9841488Smckusick usage();
9963811Shibler if (ac > 1) {
10041488Smckusick from2 = open(av[0], O_RDONLY, 0);
10141488Smckusick if (from2 < 0) {
10241488Smckusick perror("open");
10341488Smckusick exit(1);
10441488Smckusick }
10541488Smckusick n2 = av[0];
10641488Smckusick av++;
10741488Smckusick ac--;
10863811Shibler if (ac > 1) {
10963811Shibler from3 = open(av[0], O_RDONLY, 0);
11063811Shibler if (from3 < 0) {
11163811Shibler perror("open");
11263811Shibler exit(1);
11363811Shibler }
11463811Shibler n3 = av[0];
11563811Shibler av++;
11663811Shibler ac--;
11763811Shibler } else
11863811Shibler from3 = -1;
11941488Smckusick } else
12063811Shibler from2 = from3 = -1;
12141488Smckusick to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644);
12241488Smckusick if (to < 0) {
12341488Smckusick perror("open");
12441488Smckusick exit(1);
12541488Smckusick }
12641488Smckusick /* clear possibly unused directory entries */
12741488Smckusick strncpy(lifd[1].dir_name, " ", 10);
12841488Smckusick lifd[1].dir_type = -1;
12941488Smckusick lifd[1].dir_addr = 0;
13041488Smckusick lifd[1].dir_length = 0;
13141488Smckusick lifd[1].dir_flag = 0xFF;
13241488Smckusick lifd[1].dir_exec = 0;
13341488Smckusick lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
13441488Smckusick /* record volume info */
13541488Smckusick lifv.vol_id = VOL_ID;
13641488Smckusick strncpy(lifv.vol_label, "BOOT43", 6);
13757299Shibler lifv.vol_addr = btolifs(LIF_DIRSTART);
13841488Smckusick lifv.vol_oct = VOL_OCT;
13957299Shibler lifv.vol_dirsize = btolifs(LIF_DIRSIZE);
14041488Smckusick lifv.vol_version = 1;
14141488Smckusick /* output bootfile one */
14257299Shibler lseek(to, LIF_FILESTART, 0);
14341488Smckusick putfile(from1, to);
14457299Shibler n = btolifs(ld.count + sizeof(ld));
14541488Smckusick strcpy(lifd[0].dir_name, lifname(n1));
14641488Smckusick lifd[0].dir_type = DIR_TYPE;
14757299Shibler lifd[0].dir_addr = btolifs(LIF_FILESTART);
14841488Smckusick lifd[0].dir_length = n;
14954073Shibler bcddate(from1, lifd[0].dir_toc);
15041488Smckusick lifd[0].dir_flag = DIR_FLAG;
15141488Smckusick lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
15241488Smckusick lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length;
15341488Smckusick /* if there is an optional second boot program, output it */
15441488Smckusick if (from2 >= 0) {
15557299Shibler lseek(to, LIF_FILESTART+lifstob(n), 0);
15641488Smckusick putfile(from2, to);
15757299Shibler n = btolifs(ld.count + sizeof(ld));
15841488Smckusick strcpy(lifd[1].dir_name, lifname(n2));
15941488Smckusick lifd[1].dir_type = DIR_TYPE;
16057299Shibler lifd[1].dir_addr = lifv.vol_length;
16141488Smckusick lifd[1].dir_length = n;
16254073Shibler bcddate(from2, lifd[1].dir_toc);
16341488Smckusick lifd[1].dir_flag = DIR_FLAG;
16441488Smckusick lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
16541488Smckusick lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length;
16641488Smckusick }
16763811Shibler /* ditto for three */
16863811Shibler if (from3 >= 0) {
16963811Shibler lseek(to, LIF_FILESTART+lifstob(lifd[0].dir_length+n), 0);
17063811Shibler putfile(from3, to);
17163811Shibler n = btolifs(ld.count + sizeof(ld));
17263811Shibler strcpy(lifd[2].dir_name, lifname(n3));
17363811Shibler lifd[2].dir_type = DIR_TYPE;
17463811Shibler lifd[2].dir_addr = lifv.vol_length;
17563811Shibler lifd[2].dir_length = n;
17663811Shibler bcddate(from3, lifd[2].dir_toc);
17763811Shibler lifd[2].dir_flag = DIR_FLAG;
17863811Shibler lifd[2].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
17963811Shibler lifv.vol_length = lifd[2].dir_addr + lifd[2].dir_length;
18063811Shibler }
18141488Smckusick /* output volume/directory header info */
18257299Shibler lseek(to, LIF_VOLSTART, 0);
18357299Shibler write(to, &lifv, LIF_VOLSIZE);
18457299Shibler lseek(to, LIF_DIRSTART, 0);
18557299Shibler write(to, lifd, LIF_DIRSIZE);
18641488Smckusick exit(0);
18741488Smckusick }
18841488Smckusick
putfile(from,to)18941488Smckusick putfile(from, to)
19041488Smckusick {
19141488Smckusick register int n, tcnt, dcnt;
19241488Smckusick
19341488Smckusick n = read(from, &ex, sizeof(ex));
19441488Smckusick if (n != sizeof(ex)) {
19541488Smckusick fprintf(stderr, "error reading file header\n");
19641488Smckusick exit(1);
19741488Smckusick }
19841488Smckusick if (ex.a_magic == OMAGIC) {
19941488Smckusick tcnt = ex.a_text;
20041488Smckusick dcnt = ex.a_data;
20141488Smckusick }
20241488Smckusick else if (ex.a_magic == NMAGIC) {
20341488Smckusick tcnt = (ex.a_text + PGOFSET) & ~PGOFSET;
20441488Smckusick dcnt = ex.a_data;
20541488Smckusick }
20641488Smckusick else {
20741488Smckusick fprintf(stderr, "bad magic number\n");
20841488Smckusick exit(1);
20941488Smckusick }
21041488Smckusick ld.address = lpflag ? loadpoint : ex.a_entry;
21141488Smckusick ld.count = tcnt + dcnt;
21241488Smckusick write(to, &ld, sizeof(ld));
21341488Smckusick while (tcnt) {
21441488Smckusick n = sizeof(buf);
21541488Smckusick if (n > tcnt)
21641488Smckusick n = tcnt;
21741488Smckusick n = read(from, buf, n);
21841488Smckusick if (n < 0) {
21941488Smckusick perror("read");
22041488Smckusick exit(1);
22141488Smckusick }
22241488Smckusick if (n == 0) {
22341488Smckusick fprintf(stderr, "short read\n");
22441488Smckusick exit(1);
22541488Smckusick }
22641488Smckusick if (write(to, buf, n) < 0) {
22741488Smckusick perror("write");
22841488Smckusick exit(1);
22941488Smckusick }
23041488Smckusick tcnt -= n;
23141488Smckusick }
23241488Smckusick while (dcnt) {
23341488Smckusick n = sizeof(buf);
23441488Smckusick if (n > dcnt)
23541488Smckusick n = dcnt;
23641488Smckusick n = read(from, buf, n);
23741488Smckusick if (n < 0) {
23841488Smckusick perror("read");
23941488Smckusick exit(1);
24041488Smckusick }
24141488Smckusick if (n == 0) {
24241488Smckusick fprintf(stderr, "short read\n");
24341488Smckusick exit(1);
24441488Smckusick }
24541488Smckusick if (write(to, buf, n) < 0) {
24641488Smckusick perror("write");
24741488Smckusick exit(1);
24841488Smckusick }
24941488Smckusick dcnt -= n;
25041488Smckusick }
25141488Smckusick }
25241488Smckusick
usage()25341488Smckusick usage()
25441488Smckusick {
25541488Smckusick fprintf(stderr,
25641488Smckusick "usage: mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n");
25741488Smckusick exit(1);
25841488Smckusick }
25941488Smckusick
26041488Smckusick char *
lifname(str)26141488Smckusick lifname(str)
26241488Smckusick char *str;
26341488Smckusick {
26441488Smckusick static char lname[10] = "SYS_XXXXX";
26541488Smckusick register int i;
26641488Smckusick
26741488Smckusick for (i = 4; i < 9; i++) {
26841488Smckusick if (islower(*str))
26941488Smckusick lname[i] = toupper(*str);
27041488Smckusick else if (isalnum(*str) || *str == '_')
27141488Smckusick lname[i] = *str;
27241488Smckusick else
27341488Smckusick break;
27441488Smckusick str++;
27541488Smckusick }
27641488Smckusick for ( ; i < 10; i++)
27741488Smckusick lname[i] = '\0';
27841488Smckusick return(lname);
27941488Smckusick }
28054073Shibler
28156510Sbostic #include <sys/stat.h>
28256510Sbostic #include <time.h> /* XXX */
28354073Shibler
bcddate(fd,toc)28454073Shibler bcddate(fd, toc)
28554073Shibler int fd;
28654073Shibler char *toc;
28754073Shibler {
28854073Shibler struct stat statb;
28954073Shibler struct tm *tm;
29054073Shibler
29154073Shibler fstat(fd, &statb);
29254073Shibler tm = localtime(&statb.st_ctime);
29354073Shibler *toc = ((tm->tm_mon+1) / 10) << 4;
29454073Shibler *toc++ |= (tm->tm_mon+1) % 10;
29554073Shibler *toc = (tm->tm_mday / 10) << 4;
29654073Shibler *toc++ |= tm->tm_mday % 10;
29754073Shibler *toc = (tm->tm_year / 10) << 4;
29854073Shibler *toc++ |= tm->tm_year % 10;
29954073Shibler *toc = (tm->tm_hour / 10) << 4;
30054073Shibler *toc++ |= tm->tm_hour % 10;
30154073Shibler *toc = (tm->tm_min / 10) << 4;
30254073Shibler *toc++ |= tm->tm_min % 10;
30354073Shibler *toc = (tm->tm_sec / 10) << 4;
30454073Shibler *toc |= tm->tm_sec % 10;
30554073Shibler }
306