openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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 }