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