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