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