bootmaker.c (9877B)
1 /* $Id: //depot/blt/util/bootmaker.c#4 $ 2 ** 3 ** Copyright 1998 Brian J. Swetland 4 ** All rights reserved. 5 ** 6 ** Redistribution and use in source and binary forms, with or without 7 ** modification, are permitted provided that the following conditions 8 ** are met: 9 ** 1. Redistributions of source code must retain the above copyright 10 ** notice, this list of conditions, and the following disclaimer. 11 ** 2. Redistributions in binary form must reproduce the above copyright 12 ** notice, this list of conditions, and the following disclaimer in the 13 ** documentation and/or other materials provided with the distribution. 14 ** 3. The name of the author may not be used to endorse or promote products 15 ** derived from this software without specific prior written permission. 16 ** 17 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include "../include/boot.h" 29 30 #include "bootblock.h" 31 32 #include <sys/stat.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 40 static int make_floppy = 0; 41 42 void die(char *s, char *a) 43 { 44 fprintf(stderr,"error: "); 45 fprintf(stderr,s,a); 46 fprintf(stderr,"\n"); 47 exit(1); 48 } 49 50 void *loadfile(char *file, int *size) 51 { 52 int fd; 53 char *data; 54 struct stat info; 55 56 if((fd = open(file,O_RDONLY)) != -1){ 57 if(fstat(fd,&info)){ 58 close(fd); 59 *size = 0; 60 return NULL; 61 } 62 data = (char *) malloc(info.st_size); 63 if(read(fd, data, info.st_size) != info.st_size) { 64 close(fd); 65 *size = 0; 66 return NULL; 67 } 68 close(fd); 69 *size = info.st_size; 70 return data; 71 } 72 *size = 0; 73 return NULL; 74 } 75 76 /* at location 2 is a uint16, set to blocks * 8 */ 77 int writebootblock(FILE *fp, unsigned int blocks) 78 { 79 unsigned char bb[512]; 80 81 blocks *= 8; 82 83 memcpy(bb,bootblock,512); 84 85 bb[2] = (blocks & 0x00FF); 86 bb[3] = (blocks & 0xFF00) >> 8; 87 88 fwrite(bb,512,1,fp); 89 } 90 91 typedef struct _nvpair 92 { 93 struct _nvpair *next; 94 char *name; 95 char *value; 96 } nvpair; 97 98 99 typedef struct _section 100 { 101 struct _section *next; 102 char *name; 103 struct _nvpair *firstnv; 104 } section; 105 106 void print_sections(section *first) 107 { 108 nvpair *p; 109 110 while(first){ 111 printf("\n[%s]\n",first->name); 112 for(p = first->firstnv; p; p = p->next){ 113 printf("%s=%s\n",p->name,p->value); 114 } 115 first = first->next; 116 } 117 } 118 119 #ifdef xBIG_ENDIAN 120 unsigned int fix(unsigned int x) 121 { 122 int r; 123 unsigned char *a = (unsigned char *) &x; 124 unsigned char b[4]; 125 126 b[0] = a[3]; 127 b[1] = a[2]; 128 b[2] = a[1]; 129 b[3] = a[0]; 130 131 r = *((unsigned int *)b); 132 return r; 133 134 } 135 #else 136 #define fix(x) (x) 137 #endif 138 139 #define stNEWLINE 0 140 #define stSKIPLINE 1 141 #define stHEADER 2 142 #define stLHS 3 143 #define stRHS 4 144 145 section *first = NULL; 146 section *last = NULL; 147 148 section *load_ini(char *file) 149 { 150 char *data,*end; 151 int size; 152 int state = stNEWLINE; 153 section *cur; 154 155 char *lhs,*rhs; 156 157 if(!(data = loadfile(file,&size))){ 158 return NULL; 159 } 160 end = data+size; 161 162 while(data < end){ 163 switch(state){ 164 case stSKIPLINE: 165 if(*data == '\n'){ 166 state = stNEWLINE; 167 } 168 data++; 169 break; 170 171 case stNEWLINE: 172 if(*data == '\n'){ 173 data++; 174 break; 175 } 176 if(*data == '['){ 177 lhs = data+1; 178 state = stHEADER; 179 data++; 180 break; 181 } 182 if(*data == '#' || *data <= ' '){ 183 state = stSKIPLINE; 184 data++; 185 break; 186 } 187 lhs = data; 188 data++; 189 state = stLHS; 190 break; 191 case stHEADER: 192 if(*data == ']'){ 193 cur = (section *) malloc(sizeof(section)); 194 cur->name = lhs; 195 cur->firstnv = NULL; 196 cur->next = NULL; 197 if(last){ 198 last->next = cur; 199 last = cur; 200 } else { 201 last = first = cur; 202 } 203 *data = 0; 204 state = stSKIPLINE; 205 } 206 data++; 207 break; 208 case stLHS: 209 if(*data == '\n'){ 210 state = stNEWLINE; 211 } 212 if(*data == '='){ 213 *data = 0; 214 rhs = data+1; 215 state = stRHS; 216 } 217 data++; 218 continue; 219 case stRHS: 220 if(*data == '\n'){ 221 nvpair *p = (nvpair *) malloc(sizeof(nvpair)); 222 p->name = lhs; 223 p->value = rhs; 224 *data = 0; 225 p->next = cur->firstnv; 226 cur->firstnv = p; 227 state = stNEWLINE; 228 } 229 data++; 230 break; 231 } 232 } 233 return first; 234 235 } 236 237 238 char *getval(section *s, char *name) 239 { 240 nvpair *p; 241 for(p = s->firstnv; p; p = p->next){ 242 if(!strcmp(p->name,name)) return p->value; 243 } 244 return NULL; 245 } 246 247 char *getvaldef(section *s, char *name, char *def) 248 { 249 nvpair *p; 250 for(p = s->firstnv; p; p = p->next){ 251 if(!strcmp(p->name,name)) return p->value; 252 } 253 return def; 254 } 255 256 #define centry bdir.bd_entry[c] 257 void makeboot(section *s, char *outfile) 258 { 259 FILE *fp; 260 void *rawdata[64]; 261 int rawsize[64]; 262 char fill[4096]; 263 boot_dir bdir; 264 int i,c; 265 int nextpage = 1; /* page rel offset of next loaded object */ 266 267 memset(fill,0,4096); 268 269 memset(&bdir, 0, 4096); 270 for(i=0;i<64;i++){ 271 rawdata[i] = NULL; 272 rawsize[i] = 0; 273 } 274 275 c = 1; 276 277 bdir.bd_entry[0].be_type = fix(BE_TYPE_DIRECTORY); 278 bdir.bd_entry[0].be_size = fix(1); 279 bdir.bd_entry[0].be_vsize = fix(1); 280 rawdata[0] = (void *) &bdir; 281 rawsize[0] = 4096; 282 283 strcpy(bdir.bd_entry[0].be_name,"SBBB/Directory"); 284 285 while(s){ 286 char *type = getvaldef(s,"type","NONE"); 287 char *file = getval(s,"file"); 288 int vsize; 289 int size; 290 struct stat statbuf; 291 292 if(!type) die("section %s has no type",s->name); 293 294 strncpy(centry.be_name,s->name,32); 295 centry.be_name[31] = 0; 296 297 if(!file) die("section %s has no file",s->name); 298 if(!(rawdata[c] = loadfile(file,&rawsize[c]))) 299 die("cannot load \"%s\"",file); 300 301 if(stat(file,&statbuf)) 302 die("cannot stat \"%s\"",file); 303 vsize = statbuf.st_size; 304 305 centry.be_size = rawsize[c] / 4096 + (rawsize[c] % 4096 ? 1 : 0); 306 centry.be_vsize = 307 (vsize < centry.be_size) ? centry.be_size : vsize; 308 309 centry.be_offset = nextpage; 310 nextpage += centry.be_size; 311 312 centry.be_size = fix(centry.be_size); 313 centry.be_vsize = fix(centry.be_vsize); 314 centry.be_offset = fix(centry.be_offset); 315 316 if(!strcmp(type,"boot")){ 317 centry.be_type = fix(BE_TYPE_BOOTSTRAP); 318 centry.be_code_vaddr = fix(atoi(getvaldef(s,"vaddr","0"))); 319 centry.be_code_ventr = fix(atoi(getvaldef(s,"ventry","0"))); 320 } 321 if(!strcmp(type,"code")){ 322 centry.be_type = fix(BE_TYPE_CODE); 323 centry.be_code_vaddr = fix(atoi(getvaldef(s,"vaddr","0"))); 324 centry.be_code_ventr = fix(atoi(getvaldef(s,"ventry","0"))); 325 } 326 if(!strcmp(type,"data")){ 327 centry.be_type = fix(BE_TYPE_DATA); 328 } 329 if(!strcmp(type,"elf32")){ 330 centry.be_type = fix(BE_TYPE_ELF32); 331 } 332 333 if(centry.be_type == BE_TYPE_NONE){ 334 die("unrecognized section type \"%s\"",type); 335 } 336 337 c++; 338 s = s->next; 339 340 if(c==64) die("too many sections (>63)",NULL); 341 } 342 343 if(!(fp = fopen(outfile,"w"))){ 344 die("cannot write to \"%s\"",outfile); 345 } 346 347 if(make_floppy) { 348 fprintf(stderr,"whoohah!"); 349 350 writebootblock(fp, nextpage+1); 351 } 352 353 for(i=0;i<c;i++){ 354 fwrite(rawdata[i],rawsize[i],1,fp); 355 if(rawsize[i]%4096) fwrite(fill,4096 - (rawsize[i]%4096),1,fp); 356 } 357 fclose(fp); 358 359 360 } 361 362 int main(int argc, char **argv) 363 { 364 char *file = NULL; 365 section *s; 366 367 if(argc < 2){ 368 usage: 369 fprintf(stderr,"usage: %s [ --floppy | -f ] [ <inifile> ... ] -o <bootfile>\n",argv[0]); 370 return 1; 371 } 372 373 argc--; 374 argv++; 375 376 while(argc){ 377 if(!strcmp(*argv,"--floppy")){ 378 make_floppy = 1; 379 } else if(!strcmp(*argv,"-o")){ 380 argc--; 381 argv++; 382 if(argc){ 383 file = *argv; 384 } else { 385 goto usage; 386 } 387 } else { 388 if(load_ini(*argv) == NULL){ 389 fprintf(stderr,"warning: cannot load '%s'\n",*argv); 390 } 391 } 392 argc--; 393 argv++; 394 } 395 396 397 if((argc > 3) && !strcmp(argv[3],"-floppy")){ 398 make_floppy = 1; 399 } 400 401 if(!file){ 402 fprintf(stderr,"error: no output specified\n"); 403 goto usage; 404 } 405 406 if(!first){ 407 fprintf(stderr,"error: no data to write?!\n"); 408 goto usage; 409 } 410 411 makeboot(first,file); 412 413 return 0; 414 }