00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <errno.h>
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <unistd.h>
00022 #include <fcntl.h>
00023 #include <ctype.h>
00024
00025 #include <system/config.h>
00026
00027
00028 #define MAX_SI_LEN 512
00029 #define MAX_BOOT_LEN 512
00030 #define MIN_BOOT_LEN 128
00031
00032 typedef struct Target {
00033 char mode[16];
00034 char mach[16];
00035 char arch[16];
00036 unsigned int clock;
00037 unsigned char word_size;
00038 bool endianess;
00039 unsigned int mem_base;
00040 unsigned int mem_size;
00041 unsigned int cpu_type;
00042 unsigned int threads;
00043 unsigned int tasks;
00044 };
00045
00046
00047
00048 bool parse_target (char *tgt_file);
00049 void strtolower (char *dst,const char* src);
00050 bool add_machine_secrets(int fd_out,unsigned int i_size );
00051
00052 int put_buf(int fd_out, void *buf, int size);
00053 int put_file(int fd_out, char *file);
00054 int pad(int fd_out, int size);
00055 bool lil_endian();
00056
00057 template<typename T> void invert(T &n);
00058 template<typename T> int put_number(int fd_out, T num);
00059 template<typename T> bool add_boot_map (T t, int fd_out,void * _si);
00060
00061
00062 Target TARGET;
00063
00064
00065 typedef __SYS(System_Info) System_Info;
00066
00067
00068 int main(int argc, char **argv)
00069 {
00070 int i, fd_out;
00071 unsigned int image_size,si_size;
00072 unsigned int boot_size = 0;
00073 char *epos_home;
00074 char file[256];
00075 char _si[MAX_SI_LEN];
00076 struct stat file_stat;
00077 bool need_SI = true;
00078 System_Info *si = (System_Info *) _si;
00079
00080
00081 if(argc < 2) {
00082 fprintf(stderr, "Usage: %s <options> <boot image> <app1> <app2> ...\n", argv[0]);
00083 return 1;
00084 }
00085
00086
00087
00088 printf("\nEPOS bootable image tool\n\n");
00089
00090
00091
00092 epos_home = getenv("EPOS");
00093 if(epos_home == NULL) {
00094 fprintf(stderr, "Error: environment variable EPOS not set!\n");
00095 return 1;
00096 }
00097
00098
00099
00100 sprintf(file,"%s/tools/epos-mkbi/target.conf",epos_home);
00101 if(!(parse_target(file))) {
00102 fprintf(stderr, "Error: Target features file not found in <%s>\n",file);
00103 return(1);
00104 }
00105
00106
00107
00108 fd_out = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 00644);
00109 if(fd_out < 0) {
00110 fprintf(stderr, "Error: can't create boot image file \"%s\"!\n",
00111 argv[1]);
00112 return 1;
00113 }
00114
00115
00116
00117 printf(" EPOS Architecture: %s\n",TARGET.mode);
00118 printf(" Machine Target: %s\n", TARGET.mach);
00119 printf(" Processor: %s\n", TARGET.arch);
00120 printf(" Memory Amount: %d KBytes\n", TARGET.mem_size/1024);
00121 printf(" Word Size: %d bits\n", TARGET.word_size);
00122 printf(" Endianess: %s endian\n", TARGET.endianess ? "little" : "big");
00123
00124
00125
00126 image_size = 0;
00127 printf("\n Adding EPOS to => \"%s\".\n\n", argv[1]);
00128
00129
00130
00131 sprintf(file, "%s/img/%s_boot",epos_home,TARGET.mach);
00132 printf(" Boot strap \"%s\" ...", file);
00133 image_size += put_file(fd_out, file);
00134 if(image_size > MAX_BOOT_LEN) {
00135 printf(" failed!\n");
00136 fprintf(stderr, "Boot strap \"%s\" is too large! (%d bytes)\n",
00137 file, image_size);
00138 return 1;
00139 }
00140 else {
00141 while((image_size % MIN_BOOT_LEN != 0))
00142 image_size += pad(fd_out,1);
00143 boot_size = image_size;
00144 printf(" done. (%d bytes)\n",image_size);
00145 }
00146
00147
00148
00149 if (image_size == 0) {
00150 need_SI = false;
00151 }
00152 else{
00153 si_size = sizeof(System_Info);
00154 if (si_size > MAX_SI_LEN) {
00155 printf(" failed!\n");
00156 fprintf(stderr, "System Info structure is too large (%d)!\n",si_size);
00157 return 1;
00158 }
00159 else {
00160 image_size += pad(fd_out, MAX_SI_LEN);
00161 }
00162 }
00163
00164
00165
00166 si->bm.setup_off = image_size - boot_size;
00167 sprintf(file, "%s/img/%s_setup",epos_home,TARGET.mach);
00168 printf(" Setup \"%s\" ...", file);
00169 image_size += put_file(fd_out, file);
00170 printf(" done.\n");
00171
00172
00173 if (!strcmp("library",TARGET.mode)) {
00174 si->bm.system_off = -1;
00175 image_size += 0;
00176 }
00177 else {
00178
00179 si->bm.system_off = image_size - boot_size;
00180 sprintf(file, "%s/img/%s_system",epos_home,TARGET.mach);
00181 printf(" System \"%s\" ...", file);
00182 image_size += put_file(fd_out, file);
00183 printf(" done.\n");
00184 }
00185
00186
00187
00188 si->bm.loader_off = image_size - boot_size;
00189 if(argc == 3) {
00190 printf(" Single application \"%s\" ...", argv[2]);
00191 image_size += put_file(fd_out, argv[2]);
00192 } else {
00193 sprintf(file, "%s/img/%s_loader",epos_home,TARGET.mach);
00194 printf(" Loader \"%s\" ...", file);
00195 image_size += put_file(fd_out, file);
00196 }
00197 printf(" done.\n");
00198
00199
00200
00201 if (!strcmp("library",TARGET.mode)) {
00202 si->bm.app_off = -1;
00203 image_size += 0;
00204 if (argc > 3)
00205 printf("\n Warning: --library mode just supports one application or remote loading\n");
00206 }
00207 else {
00208 si->bm.app_off = image_size - boot_size;
00209 if(argc > 3) {
00210 printf("Adding applications =>");
00211 for(i = 2; i < argc; i++) {
00212 printf(" %s ...", argv[i]);
00213 stat(argv[i], &file_stat);
00214 image_size += put_number(fd_out, file_stat.st_size);
00215 image_size += put_file(fd_out, argv[i]);
00216 printf (" done.\n");
00217 }
00218
00219 image_size += put_number(fd_out, 0);
00220 }
00221 }
00222
00223
00224
00225 si->bm.mem_base = TARGET.mem_base;
00226 si->bm.mem_size = TARGET.mem_size;
00227 si->bm.cpu_type = TARGET.cpu_type;;
00228 si->bm.cpu_clock = TARGET.clock;
00229 si->bm.host_id = (unsigned short)-1;
00230 si->bm.n_threads = TARGET.threads;
00231 si->bm.n_tasks = TARGET.tasks;
00232 si->bm.img_size = image_size - boot_size;
00233
00234
00235 if (need_SI) {
00236
00237 if(lseek(fd_out, boot_size, SEEK_SET) < 0) {
00238 fprintf(stderr, "Error: can not seek the boot image!\n");
00239 return 1;
00240 }
00241 switch (TARGET.word_size) {
00242
00243 case (8): if(!add_boot_map((char) NULL,fd_out,si)) return(1);
00244 break;
00245 case (16): if(!add_boot_map((short) NULL,fd_out,si)) return(1);
00246 break;
00247 case (32): if(!add_boot_map((long) NULL,fd_out,si)) return(1);
00248 break;
00249 case (64): if(!add_boot_map((long long) NULL,fd_out,si)) return(1);
00250 break;
00251 default: return 1;
00252 }
00253 }
00254
00255
00256
00257
00258 printf("\n Adding specific boot features of %s!\n",TARGET.mach);
00259 if(!(add_machine_secrets(fd_out,image_size))) {
00260 fprintf(stderr, "Error: specific features error!\n");
00261 return 1;
00262 }
00263
00264
00265 close(fd_out);
00266 printf("\n Image size: %d bytes.\n\n",image_size);
00267
00268 return 0;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 bool parse_target(char* tgt_file) {
00285
00286 char line[256];
00287 char* token;
00288 FILE * f = NULL;
00289 if (!(f=fopen(tgt_file,"rb"))) goto err;
00290
00291
00292 fgets(line,255,f);
00293 token=strtok(line,"=");
00294 if (strcmp(token,"MODE") != 0) goto err;
00295 token=strtok(NULL,"\n");
00296 strtolower(TARGET.mode,token);
00297
00298
00299 fgets(line,255,f);
00300 token=strtok(line,"=");
00301 if (strcmp(token,"MACH") != 0) goto err;
00302 token=strtok(NULL,"\n");
00303 strtolower(TARGET.mach,token);
00304
00305
00306 fgets(line,255,f);
00307 token=strtok(line,"=");
00308 if (strcmp(token,"ARCH") != 0) goto err;
00309 token=strtok(NULL,"\n");
00310 strtolower(TARGET.arch,token);
00311
00312
00313 fgets(line,255,f);
00314 token=strtok(line,"=");
00315 if (strcmp(token,"CLOCK") != 0) goto err;
00316 token=strtok(NULL,"\n");
00317 TARGET.clock=atoi(token);
00318
00319
00320 fgets(line,255,f);
00321 token=strtok(line,"=");
00322 if (strcmp(token,"WORD_SIZE") != 0) goto err;
00323 token=strtok(NULL,"\n");
00324 TARGET.word_size=atoi(token);
00325
00326
00327 fgets(line,255,f);
00328 token=strtok(line,"=");
00329 if (strcmp(token,"ENDIANESS") != 0) goto err;
00330 token=strtok(NULL,"\n");
00331 if (strcmp(token,"little") == 0) TARGET.endianess = true;
00332 else TARGET.endianess = false;
00333
00334
00335 fgets(line,255,f);
00336 token=strtok(line,"=");
00337 if (strcmp(token,"MEM_BASE") != 0) goto err;
00338 token=strtok(NULL,"\n");
00339 TARGET.mem_base=atoi(token);
00340
00341
00342 fgets(line,255,f);
00343 token=strtok(line,"=");
00344 if (strcmp(token,"MEM_SIZE") != 0) goto err;
00345 token=strtok(NULL,"\n");
00346 TARGET.mem_size=atoi(token);
00347
00348 TARGET.cpu_type = 0;
00349 TARGET.threads = 8;
00350 TARGET.tasks = 1;
00351
00352 fclose(f);
00353 return(true);
00354
00355 err:
00356 if (f) fclose(f);
00357 return(false);
00358 }
00359
00360
00361 void strtolower(char* dst, const char* src) {
00362 int i = 0;
00363 strcpy(dst,src);
00364 while(src[i] != '\0') {
00365 dst[i] = tolower(dst[i]);
00366 i++;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 template<typename T> bool add_boot_map (T t, int fd_out, void * _si) {
00384
00385 System_Info * si = (System_Info *) _si;
00386
00387 pad(fd_out, (3*sizeof(T)));
00388
00389 if(!put_number(fd_out,(T) si->bm.mem_base)) return(false);
00390 if(!put_number(fd_out,(T) si->bm.mem_size)) return(false);
00391 if(!put_number(fd_out,(T) si->bm.cpu_type)) return(false);
00392 if(!put_number(fd_out,(T) si->bm.cpu_clock)) return(false);
00393 if(!put_number(fd_out,(T) si->bm.n_threads)) return(false);
00394 if(!put_number(fd_out,(T) si->bm.n_tasks)) return(false);
00395
00396 if(!put_number(fd_out,si->bm.host_id)) return(false);
00397 if(!put_number(fd_out,si->bm.n_nodes)) return(false);
00398
00399 if(!put_number(fd_out,(T) si->bm.img_size)) return(false);
00400 if(!put_number(fd_out,(T) si->bm.setup_off)) return(false);
00401 if(!put_number(fd_out,(T) si->bm.system_off)) return(false);
00402 if(!put_number(fd_out,(T) si->bm.loader_off)) return(false);
00403 if(!put_number(fd_out,(T) si->bm.app_off)) return(false);
00404
00405 return(true);
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 bool add_machine_secrets(int fd_out, unsigned int i_size) {
00421
00422
00423 if (strcmp("pc",TARGET.mach) == 0) {
00424 const unsigned int floppy_size = 1474560;
00425 const unsigned short count_offset = 508;
00426 const unsigned short master_offset = 510;
00427 unsigned short boot_id = 0xaa55;
00428 unsigned short num_sect = ((i_size + 511) / 512);
00429
00430
00431 if(lseek(fd_out, 0, SEEK_END) < 0) {
00432 fprintf(stderr, "Error: can not seek the boot image!\n");
00433 return false;
00434 }
00435 pad(fd_out, (floppy_size - i_size));
00436
00437
00438 if(lseek(fd_out, count_offset, SEEK_SET) < 0) {
00439 fprintf(stderr, "Error: can not seek the boot image!\n");
00440 return false;
00441 }
00442 put_number(fd_out,num_sect);
00443
00444
00445 if(lseek(fd_out, master_offset, SEEK_SET) < 0) {
00446 fprintf(stderr, "Error: can not seek the boot image!\n");
00447 return false;
00448 }
00449 put_number(fd_out, boot_id);
00450
00451 return(true);
00452 }
00453
00454
00455 else if (strcmp("rcx",TARGET.mach) == 0) {
00456 char* key_string = "Do you byte, when I knock?";
00457 const unsigned short key_offset = 128 - (strlen(key_string) + 1);
00458
00459
00460 if(lseek(fd_out,key_offset,SEEK_SET) < 0) {
00461 fprintf(stderr, "Error: can not seek the boot image!\n");
00462 return false;
00463 }
00464 put_buf(fd_out, key_string, (strlen(key_string)+1));
00465 return(true);
00466 }
00467
00468 return(true);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 bool lil_endian() {
00485 int test = 1;
00486 return (*((char*)&test)) ? true : false;
00487 }
00488
00489 template<typename T> void invert(T &n) {
00490 for (int i=0,j=(sizeof(T) - 1); i<((int)(sizeof(T)/2));i++,j--) {
00491 char *h = &(((char *)&n)[i]);
00492 char *l = &(((char *)&n)[j]);
00493 *h ^= *l;
00494 *l ^= *h;
00495 *h ^= *l;
00496 }
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 int put_file(int fd_out, char * file)
00513 {
00514 int fd_in;
00515 struct stat stat;
00516 char * buffer;
00517
00518 fd_in = open(file, O_RDONLY);
00519 if(fd_in < 0) {
00520 fprintf(stderr, "Error: can not open %s!\n", file);
00521 return 0;
00522 }
00523
00524 if(fstat(fd_in, &stat) < 0) {
00525 fprintf(stderr, "Error: can not stat %s!\n", file);
00526 return 0;
00527 }
00528
00529 buffer = (char *) malloc(stat.st_size);
00530 if(buffer == NULL) {
00531 fprintf(stderr, "Error: not enough memory!\n");
00532 return 0;
00533 }
00534 memset(buffer, '\1', stat.st_size);
00535
00536 if(read(fd_in, buffer, stat.st_size) < 0) {
00537 fprintf(stderr, "Error: can not read from %s!\n", file);
00538 return 0;
00539 }
00540
00541 if(write(fd_out, buffer, stat.st_size) < 0) {
00542 fprintf(stderr, "Error: can not write to the boot image!\n");
00543 return 0;
00544 }
00545
00546 free(buffer);
00547 close(fd_in);
00548
00549 return(stat.st_size);
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 template<typename T> int put_number(int fd_out, T num)
00566 {
00567 if ((lil_endian() != TARGET.endianess) && (sizeof(T) > 1))
00568 invert(num);
00569 if(write(fd_out, &num, sizeof(T)) < 0) {
00570 fprintf(stderr, "Error: can not wirte to file!\n");
00571 return 0;
00572 }
00573 return sizeof(T);
00574 }
00575
00576
00577 int put_buf(int fd_out, void * buf, int size)
00578 {
00579 int written;
00580 if (size == 0) return(0);
00581 if((written = write(fd_out, buf, size)) < 0) {
00582 fprintf(stderr, "Error: can not wirte to file!\n");
00583 return 0;
00584 }
00585 return written;
00586 }
00587
00588
00589 int pad(int fd_out, int size)
00590 {
00591 char * buffer;
00592 if (size == 0) return(0);
00593
00594 buffer = (char *) malloc(size);
00595 if(buffer == NULL) {
00596 fprintf(stderr, "Error: not enough memory!\n");
00597 return 0;
00598 }
00599
00600 memset(buffer,'\1', size);
00601 if(write(fd_out, buffer, size) < 0) {
00602 fprintf(stderr, "Error: can not write to the boot image!\n");
00603 return 0;
00604 }
00605 if(buffer != NULL) free(buffer);
00606 return size;
00607 }