141488Smckusick /* 241488Smckusick * Copyright (c) 1990 The Regents of the University of California. 341488Smckusick * All rights reserved. 441488Smckusick * 541488Smckusick * %sccs.include.redist.c% 641488Smckusick * 7*63811Shibler * @(#)mkboot.c 7.6 (Berkeley) 07/15/93 841488Smckusick */ 941488Smckusick 1041488Smckusick #ifndef lint 11*63811Shibler static char copyright[] = 12*63811Shibler "@(#) Copyright (c) 1990, 1993\n\ 13*63811Shibler 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 */ 6441488Smckusick main(argc, argv) 6541488Smckusick char **argv; 6641488Smckusick { 6741488Smckusick int ac; 6841488Smckusick char **av; 69*63811Shibler int from1, from2, from3, to; 7041488Smckusick register int n; 71*63811Shibler 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(); 99*63811Shibler 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--; 108*63811Shibler if (ac > 1) { 109*63811Shibler from3 = open(av[0], O_RDONLY, 0); 110*63811Shibler if (from3 < 0) { 111*63811Shibler perror("open"); 112*63811Shibler exit(1); 113*63811Shibler } 114*63811Shibler n3 = av[0]; 115*63811Shibler av++; 116*63811Shibler ac--; 117*63811Shibler } else 118*63811Shibler from3 = -1; 11941488Smckusick } else 120*63811Shibler 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 } 167*63811Shibler /* ditto for three */ 168*63811Shibler if (from3 >= 0) { 169*63811Shibler lseek(to, LIF_FILESTART+lifstob(lifd[0].dir_length+n), 0); 170*63811Shibler putfile(from3, to); 171*63811Shibler n = btolifs(ld.count + sizeof(ld)); 172*63811Shibler strcpy(lifd[2].dir_name, lifname(n3)); 173*63811Shibler lifd[2].dir_type = DIR_TYPE; 174*63811Shibler lifd[2].dir_addr = lifv.vol_length; 175*63811Shibler lifd[2].dir_length = n; 176*63811Shibler bcddate(from3, lifd[2].dir_toc); 177*63811Shibler lifd[2].dir_flag = DIR_FLAG; 178*63811Shibler lifd[2].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry; 179*63811Shibler lifv.vol_length = lifd[2].dir_addr + lifd[2].dir_length; 180*63811Shibler } 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 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 25341488Smckusick usage() 25441488Smckusick { 25541488Smckusick fprintf(stderr, 25641488Smckusick "usage: mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n"); 25741488Smckusick exit(1); 25841488Smckusick } 25941488Smckusick 26041488Smckusick char * 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 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