141488Smckusick /* 241488Smckusick * Copyright (c) 1990 The Regents of the University of California. 341488Smckusick * All rights reserved. 441488Smckusick * 541488Smckusick * %sccs.include.redist.c% 641488Smckusick * 7*57299Shibler * @(#)mkboot.c 7.5 (Berkeley) 12/26/92 841488Smckusick */ 941488Smckusick 1041488Smckusick #ifndef lint 1141488Smckusick char copyright[] = 1241488Smckusick "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 1341488Smckusick 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 29*57299Shibler #define LIF_NUMDIR 8 30*57299Shibler 31*57299Shibler #define LIF_VOLSTART 0 32*57299Shibler #define LIF_VOLSIZE sizeof(struct lifvol) 33*57299Shibler #define LIF_DIRSTART 512 34*57299Shibler #define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir)) 35*57299Shibler #define LIF_FILESTART 8192 36*57299Shibler 37*57299Shibler #define btolifs(b) (((b) + (SECTSIZE - 1)) / SECTSIZE) 38*57299Shibler #define lifstob(s) ((s) * SECTSIZE) 39*57299Shibler 4041488Smckusick int lpflag; 4141488Smckusick int loadpoint; 4241488Smckusick struct load ld; 4341488Smckusick struct lifvol lifv; 44*57299Shibler struct lifdir lifd[LIF_NUMDIR]; 4541488Smckusick struct exec ex; 4641488Smckusick char buf[10240]; 4741488Smckusick 48*57299Shibler /* 49*57299Shibler * Old Format: 50*57299Shibler * sector 0: LIF volume header (40 bytes) 51*57299Shibler * sector 1: <unused> 52*57299Shibler * sector 2: LIF directory (8 x 32 == 256 bytes) 53*57299Shibler * sector 3-: LIF file 0, LIF file 1, etc. 54*57299Shibler * where sectors are 256 bytes. 55*57299Shibler * 56*57299Shibler * New Format: 57*57299Shibler * sector 0: LIF volume header (40 bytes) 58*57299Shibler * sector 1: <unused> 59*57299Shibler * sector 2: LIF directory (8 x 32 == 256 bytes) 60*57299Shibler * sector 3: <unused> 61*57299Shibler * sector 4-31: disklabel (~300 bytes right now) 62*57299Shibler * sector 32-: LIF file 0, LIF file 1, etc. 63*57299Shibler */ 6441488Smckusick main(argc, argv) 6541488Smckusick char **argv; 6641488Smckusick { 6741488Smckusick int ac; 6841488Smckusick char **av; 6941488Smckusick int from1, from2, to; 7041488Smckusick register int n; 7141488Smckusick char *n1, *n2, *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(); 9941488Smckusick if (ac == 2) { 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--; 10841488Smckusick } else 10941488Smckusick from2 = -1; 11041488Smckusick to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644); 11141488Smckusick if (to < 0) { 11241488Smckusick perror("open"); 11341488Smckusick exit(1); 11441488Smckusick } 11541488Smckusick /* clear possibly unused directory entries */ 11641488Smckusick strncpy(lifd[1].dir_name, " ", 10); 11741488Smckusick lifd[1].dir_type = -1; 11841488Smckusick lifd[1].dir_addr = 0; 11941488Smckusick lifd[1].dir_length = 0; 12041488Smckusick lifd[1].dir_flag = 0xFF; 12141488Smckusick lifd[1].dir_exec = 0; 12241488Smckusick lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1]; 12341488Smckusick /* record volume info */ 12441488Smckusick lifv.vol_id = VOL_ID; 12541488Smckusick strncpy(lifv.vol_label, "BOOT43", 6); 126*57299Shibler lifv.vol_addr = btolifs(LIF_DIRSTART); 12741488Smckusick lifv.vol_oct = VOL_OCT; 128*57299Shibler lifv.vol_dirsize = btolifs(LIF_DIRSIZE); 12941488Smckusick lifv.vol_version = 1; 13041488Smckusick /* output bootfile one */ 131*57299Shibler lseek(to, LIF_FILESTART, 0); 13241488Smckusick putfile(from1, to); 133*57299Shibler n = btolifs(ld.count + sizeof(ld)); 13441488Smckusick strcpy(lifd[0].dir_name, lifname(n1)); 13541488Smckusick lifd[0].dir_type = DIR_TYPE; 136*57299Shibler lifd[0].dir_addr = btolifs(LIF_FILESTART); 13741488Smckusick lifd[0].dir_length = n; 13854073Shibler bcddate(from1, lifd[0].dir_toc); 13941488Smckusick lifd[0].dir_flag = DIR_FLAG; 14041488Smckusick lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry; 14141488Smckusick lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length; 14241488Smckusick /* if there is an optional second boot program, output it */ 14341488Smckusick if (from2 >= 0) { 144*57299Shibler lseek(to, LIF_FILESTART+lifstob(n), 0); 14541488Smckusick putfile(from2, to); 146*57299Shibler n = btolifs(ld.count + sizeof(ld)); 14741488Smckusick strcpy(lifd[1].dir_name, lifname(n2)); 14841488Smckusick lifd[1].dir_type = DIR_TYPE; 149*57299Shibler lifd[1].dir_addr = lifv.vol_length; 15041488Smckusick lifd[1].dir_length = n; 15154073Shibler bcddate(from2, lifd[1].dir_toc); 15241488Smckusick lifd[1].dir_flag = DIR_FLAG; 15341488Smckusick lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry; 15441488Smckusick lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length; 15541488Smckusick } 15641488Smckusick /* output volume/directory header info */ 157*57299Shibler lseek(to, LIF_VOLSTART, 0); 158*57299Shibler write(to, &lifv, LIF_VOLSIZE); 159*57299Shibler lseek(to, LIF_DIRSTART, 0); 160*57299Shibler write(to, lifd, LIF_DIRSIZE); 16141488Smckusick exit(0); 16241488Smckusick } 16341488Smckusick 16441488Smckusick putfile(from, to) 16541488Smckusick { 16641488Smckusick register int n, tcnt, dcnt; 16741488Smckusick 16841488Smckusick n = read(from, &ex, sizeof(ex)); 16941488Smckusick if (n != sizeof(ex)) { 17041488Smckusick fprintf(stderr, "error reading file header\n"); 17141488Smckusick exit(1); 17241488Smckusick } 17341488Smckusick if (ex.a_magic == OMAGIC) { 17441488Smckusick tcnt = ex.a_text; 17541488Smckusick dcnt = ex.a_data; 17641488Smckusick } 17741488Smckusick else if (ex.a_magic == NMAGIC) { 17841488Smckusick tcnt = (ex.a_text + PGOFSET) & ~PGOFSET; 17941488Smckusick dcnt = ex.a_data; 18041488Smckusick } 18141488Smckusick else { 18241488Smckusick fprintf(stderr, "bad magic number\n"); 18341488Smckusick exit(1); 18441488Smckusick } 18541488Smckusick ld.address = lpflag ? loadpoint : ex.a_entry; 18641488Smckusick ld.count = tcnt + dcnt; 18741488Smckusick write(to, &ld, sizeof(ld)); 18841488Smckusick while (tcnt) { 18941488Smckusick n = sizeof(buf); 19041488Smckusick if (n > tcnt) 19141488Smckusick n = tcnt; 19241488Smckusick n = read(from, buf, n); 19341488Smckusick if (n < 0) { 19441488Smckusick perror("read"); 19541488Smckusick exit(1); 19641488Smckusick } 19741488Smckusick if (n == 0) { 19841488Smckusick fprintf(stderr, "short read\n"); 19941488Smckusick exit(1); 20041488Smckusick } 20141488Smckusick if (write(to, buf, n) < 0) { 20241488Smckusick perror("write"); 20341488Smckusick exit(1); 20441488Smckusick } 20541488Smckusick tcnt -= n; 20641488Smckusick } 20741488Smckusick while (dcnt) { 20841488Smckusick n = sizeof(buf); 20941488Smckusick if (n > dcnt) 21041488Smckusick n = dcnt; 21141488Smckusick n = read(from, buf, n); 21241488Smckusick if (n < 0) { 21341488Smckusick perror("read"); 21441488Smckusick exit(1); 21541488Smckusick } 21641488Smckusick if (n == 0) { 21741488Smckusick fprintf(stderr, "short read\n"); 21841488Smckusick exit(1); 21941488Smckusick } 22041488Smckusick if (write(to, buf, n) < 0) { 22141488Smckusick perror("write"); 22241488Smckusick exit(1); 22341488Smckusick } 22441488Smckusick dcnt -= n; 22541488Smckusick } 22641488Smckusick } 22741488Smckusick 22841488Smckusick usage() 22941488Smckusick { 23041488Smckusick fprintf(stderr, 23141488Smckusick "usage: mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n"); 23241488Smckusick exit(1); 23341488Smckusick } 23441488Smckusick 23541488Smckusick char * 23641488Smckusick lifname(str) 23741488Smckusick char *str; 23841488Smckusick { 23941488Smckusick static char lname[10] = "SYS_XXXXX"; 24041488Smckusick register int i; 24141488Smckusick 24241488Smckusick for (i = 4; i < 9; i++) { 24341488Smckusick if (islower(*str)) 24441488Smckusick lname[i] = toupper(*str); 24541488Smckusick else if (isalnum(*str) || *str == '_') 24641488Smckusick lname[i] = *str; 24741488Smckusick else 24841488Smckusick break; 24941488Smckusick str++; 25041488Smckusick } 25141488Smckusick for ( ; i < 10; i++) 25241488Smckusick lname[i] = '\0'; 25341488Smckusick return(lname); 25441488Smckusick } 25554073Shibler 25656510Sbostic #include <sys/stat.h> 25756510Sbostic #include <time.h> /* XXX */ 25854073Shibler 25954073Shibler bcddate(fd, toc) 26054073Shibler int fd; 26154073Shibler char *toc; 26254073Shibler { 26354073Shibler struct stat statb; 26454073Shibler struct tm *tm; 26554073Shibler 26654073Shibler fstat(fd, &statb); 26754073Shibler tm = localtime(&statb.st_ctime); 26854073Shibler *toc = ((tm->tm_mon+1) / 10) << 4; 26954073Shibler *toc++ |= (tm->tm_mon+1) % 10; 27054073Shibler *toc = (tm->tm_mday / 10) << 4; 27154073Shibler *toc++ |= tm->tm_mday % 10; 27254073Shibler *toc = (tm->tm_year / 10) << 4; 27354073Shibler *toc++ |= tm->tm_year % 10; 27454073Shibler *toc = (tm->tm_hour / 10) << 4; 27554073Shibler *toc++ |= tm->tm_hour % 10; 27654073Shibler *toc = (tm->tm_min / 10) << 4; 27754073Shibler *toc++ |= tm->tm_min % 10; 27854073Shibler *toc = (tm->tm_sec / 10) << 4; 27954073Shibler *toc |= tm->tm_sec % 10; 28054073Shibler } 281