1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mkboot.c 7.5 (Berkeley) 12/26/92 8 */ 9 10 #ifndef lint 11 char copyright[] = 12 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 13 All rights reserved.\n"; 14 #endif /* not lint */ 15 16 #ifndef lint 17 static char sccsid[] = "@(#)mkboot.c 7.2 (Berkeley) 12/16/90"; 18 #endif /* not lint */ 19 20 #include <sys/param.h> 21 #include <sys/exec.h> 22 #include <sys/file.h> 23 24 #include <hp300/stand/volhdr.h> 25 26 #include <stdio.h> 27 #include <ctype.h> 28 29 #define LIF_NUMDIR 8 30 31 #define LIF_VOLSTART 0 32 #define LIF_VOLSIZE sizeof(struct lifvol) 33 #define LIF_DIRSTART 512 34 #define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir)) 35 #define LIF_FILESTART 8192 36 37 #define btolifs(b) (((b) + (SECTSIZE - 1)) / SECTSIZE) 38 #define lifstob(s) ((s) * SECTSIZE) 39 40 int lpflag; 41 int loadpoint; 42 struct load ld; 43 struct lifvol lifv; 44 struct lifdir lifd[LIF_NUMDIR]; 45 struct exec ex; 46 char buf[10240]; 47 48 /* 49 * Old Format: 50 * sector 0: LIF volume header (40 bytes) 51 * sector 1: <unused> 52 * sector 2: LIF directory (8 x 32 == 256 bytes) 53 * sector 3-: LIF file 0, LIF file 1, etc. 54 * where sectors are 256 bytes. 55 * 56 * New Format: 57 * sector 0: LIF volume header (40 bytes) 58 * sector 1: <unused> 59 * sector 2: LIF directory (8 x 32 == 256 bytes) 60 * sector 3: <unused> 61 * sector 4-31: disklabel (~300 bytes right now) 62 * sector 32-: LIF file 0, LIF file 1, etc. 63 */ 64 main(argc, argv) 65 char **argv; 66 { 67 int ac; 68 char **av; 69 int from1, from2, to; 70 register int n; 71 char *n1, *n2, *lifname(); 72 73 ac = --argc; 74 av = ++argv; 75 if (ac == 0) 76 usage(); 77 if (!strcmp(av[0], "-l")) { 78 av++; 79 ac--; 80 if (ac == 0) 81 usage(); 82 sscanf(av[0], "0x%x", &loadpoint); 83 lpflag++; 84 av++; 85 ac--; 86 } 87 if (ac == 0) 88 usage(); 89 from1 = open(av[0], O_RDONLY, 0); 90 if (from1 < 0) { 91 perror("open"); 92 exit(1); 93 } 94 n1 = av[0]; 95 av++; 96 ac--; 97 if (ac == 0) 98 usage(); 99 if (ac == 2) { 100 from2 = open(av[0], O_RDONLY, 0); 101 if (from2 < 0) { 102 perror("open"); 103 exit(1); 104 } 105 n2 = av[0]; 106 av++; 107 ac--; 108 } else 109 from2 = -1; 110 to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644); 111 if (to < 0) { 112 perror("open"); 113 exit(1); 114 } 115 /* clear possibly unused directory entries */ 116 strncpy(lifd[1].dir_name, " ", 10); 117 lifd[1].dir_type = -1; 118 lifd[1].dir_addr = 0; 119 lifd[1].dir_length = 0; 120 lifd[1].dir_flag = 0xFF; 121 lifd[1].dir_exec = 0; 122 lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1]; 123 /* record volume info */ 124 lifv.vol_id = VOL_ID; 125 strncpy(lifv.vol_label, "BOOT43", 6); 126 lifv.vol_addr = btolifs(LIF_DIRSTART); 127 lifv.vol_oct = VOL_OCT; 128 lifv.vol_dirsize = btolifs(LIF_DIRSIZE); 129 lifv.vol_version = 1; 130 /* output bootfile one */ 131 lseek(to, LIF_FILESTART, 0); 132 putfile(from1, to); 133 n = btolifs(ld.count + sizeof(ld)); 134 strcpy(lifd[0].dir_name, lifname(n1)); 135 lifd[0].dir_type = DIR_TYPE; 136 lifd[0].dir_addr = btolifs(LIF_FILESTART); 137 lifd[0].dir_length = n; 138 bcddate(from1, lifd[0].dir_toc); 139 lifd[0].dir_flag = DIR_FLAG; 140 lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry; 141 lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length; 142 /* if there is an optional second boot program, output it */ 143 if (from2 >= 0) { 144 lseek(to, LIF_FILESTART+lifstob(n), 0); 145 putfile(from2, to); 146 n = btolifs(ld.count + sizeof(ld)); 147 strcpy(lifd[1].dir_name, lifname(n2)); 148 lifd[1].dir_type = DIR_TYPE; 149 lifd[1].dir_addr = lifv.vol_length; 150 lifd[1].dir_length = n; 151 bcddate(from2, lifd[1].dir_toc); 152 lifd[1].dir_flag = DIR_FLAG; 153 lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry; 154 lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length; 155 } 156 /* output volume/directory header info */ 157 lseek(to, LIF_VOLSTART, 0); 158 write(to, &lifv, LIF_VOLSIZE); 159 lseek(to, LIF_DIRSTART, 0); 160 write(to, lifd, LIF_DIRSIZE); 161 exit(0); 162 } 163 164 putfile(from, to) 165 { 166 register int n, tcnt, dcnt; 167 168 n = read(from, &ex, sizeof(ex)); 169 if (n != sizeof(ex)) { 170 fprintf(stderr, "error reading file header\n"); 171 exit(1); 172 } 173 if (ex.a_magic == OMAGIC) { 174 tcnt = ex.a_text; 175 dcnt = ex.a_data; 176 } 177 else if (ex.a_magic == NMAGIC) { 178 tcnt = (ex.a_text + PGOFSET) & ~PGOFSET; 179 dcnt = ex.a_data; 180 } 181 else { 182 fprintf(stderr, "bad magic number\n"); 183 exit(1); 184 } 185 ld.address = lpflag ? loadpoint : ex.a_entry; 186 ld.count = tcnt + dcnt; 187 write(to, &ld, sizeof(ld)); 188 while (tcnt) { 189 n = sizeof(buf); 190 if (n > tcnt) 191 n = tcnt; 192 n = read(from, buf, n); 193 if (n < 0) { 194 perror("read"); 195 exit(1); 196 } 197 if (n == 0) { 198 fprintf(stderr, "short read\n"); 199 exit(1); 200 } 201 if (write(to, buf, n) < 0) { 202 perror("write"); 203 exit(1); 204 } 205 tcnt -= n; 206 } 207 while (dcnt) { 208 n = sizeof(buf); 209 if (n > dcnt) 210 n = dcnt; 211 n = read(from, buf, n); 212 if (n < 0) { 213 perror("read"); 214 exit(1); 215 } 216 if (n == 0) { 217 fprintf(stderr, "short read\n"); 218 exit(1); 219 } 220 if (write(to, buf, n) < 0) { 221 perror("write"); 222 exit(1); 223 } 224 dcnt -= n; 225 } 226 } 227 228 usage() 229 { 230 fprintf(stderr, 231 "usage: mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n"); 232 exit(1); 233 } 234 235 char * 236 lifname(str) 237 char *str; 238 { 239 static char lname[10] = "SYS_XXXXX"; 240 register int i; 241 242 for (i = 4; i < 9; i++) { 243 if (islower(*str)) 244 lname[i] = toupper(*str); 245 else if (isalnum(*str) || *str == '_') 246 lname[i] = *str; 247 else 248 break; 249 str++; 250 } 251 for ( ; i < 10; i++) 252 lname[i] = '\0'; 253 return(lname); 254 } 255 256 #include <sys/stat.h> 257 #include <time.h> /* XXX */ 258 259 bcddate(fd, toc) 260 int fd; 261 char *toc; 262 { 263 struct stat statb; 264 struct tm *tm; 265 266 fstat(fd, &statb); 267 tm = localtime(&statb.st_ctime); 268 *toc = ((tm->tm_mon+1) / 10) << 4; 269 *toc++ |= (tm->tm_mon+1) % 10; 270 *toc = (tm->tm_mday / 10) << 4; 271 *toc++ |= tm->tm_mday % 10; 272 *toc = (tm->tm_year / 10) << 4; 273 *toc++ |= tm->tm_year % 10; 274 *toc = (tm->tm_hour / 10) << 4; 275 *toc++ |= tm->tm_hour % 10; 276 *toc = (tm->tm_min / 10) << 4; 277 *toc++ |= tm->tm_min % 10; 278 *toc = (tm->tm_sec / 10) << 4; 279 *toc |= tm->tm_sec % 10; 280 } 281