📄 mkcsysimg.c
字号:
DBG(1,"writing header for block"); res = write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr),NULL); return res;}intblock_writeout_file(FILE *outfile, struct csys_block *block){ char buf[FILE_BUF_LEN]; size_t buflen = sizeof(buf); FILE *f; size_t len; int res; if (block->file_name == NULL) return 0; if (block->file_size == 0) return 0; errno = 0; f = fopen(block->file_name,"r"); if (errno) { ERRS("unable to open file: %s", block->file_name); return ERR_FATAL; } len = block->file_size; while (len > 0) { if (len < buflen) buflen = len; /* read data from source file */ errno = 0; fread(buf, buflen, 1, f); if (errno != 0) { ERRS("unable to read from file: %s", block->file_name); res = ERR_FATAL; break; } res = write_out_data(outfile, buf, buflen, block->css); if (res) break; len -= buflen; } fclose(f); return res;}intblock_writeout_data(FILE *outfile, struct csys_block *block){ int res; size_t padlen; res = block_writeout_file(outfile, block); if (res) return res; /* write padding data if neccesary */ padlen = block->size_avail - block->file_size; DBG(1,"padding block, length=%d", padlen); res = write_out_padding(outfile, padlen, block->padc, block->css); return res;}intblock_writeout_csum(FILE *outfile, struct csys_block *block){ uint16_t csum; int res; if (block->size_csum == 0) return 0; DBG(1,"writing checksum for block"); csum = HOST_TO_LE16(csum_get(block->css)); res = write_out_data(outfile, (uint8_t *)&csum, block->size_csum, NULL); return res;}intblock_writeout(FILE *outfile, struct csys_block *block){ int res; struct csum_state css; res = 0; if (block == NULL) return res; block->css = NULL; DBG(2, "writing block, file=%s, file_size=%d, space=%d", block->file_name, block->file_size, block->size_avail); res = block_writeout_hdr(outfile, block); if (res) return res; if (block->size_csum != 0) { block->css = &css; csum_init(&css, block->size_csum); } res = block_writeout_data(outfile, block); if (res) return res; res = block_writeout_csum(outfile, block); if (res) return res; return res;}intwrite_out_blocks(FILE *outfile){ struct csys_block *block; int i, res; res = block_writeout(outfile, boot_block); if (res) return res; res = block_writeout(outfile, conf_block); if (res) return res; res = block_writeout(outfile, webp_block); if (res) return res; res = block_writeout(outfile, code_block); if (res) return res; res = 0; for (i=0; i < num_blocks; i++) { block = &blocks[i]; if (block->type != BLOCK_TYPE_XTRA) continue; res = block_writeout(outfile, block); if (res) break; } return res;}struct board_info *find_board(char *model){ struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->model != NULL; board++){ if (strcasecmp(model, board->model) == 0) { ret = board; break; } }; return ret;}intparse_opt_board(char ch, char *arg){ DBG(1,"parsing board option: -%c %s", ch, arg); if (board != NULL) { ERR("only one board option allowed"); return ERR_FATAL; } if (required_arg(ch, arg)) return ERR_FATAL; board = find_board(arg); if (board == NULL){ ERR("invalid/unknown board specified: %s", arg); return ERR_FATAL; } return 0;}intparse_opt_block(char ch, char *arg){ char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; struct csys_block *block; int i; if ( num_blocks > MAX_NUM_BLOCKS ) { ERR("too many blocks specified"); return ERR_FATAL; } block = &blocks[num_blocks]; /* setup default field values */ block->need_file = 1; block->padc = 0xFF; switch (ch) { case 'b': if (boot_block) { WARN("only one boot block allowed"); break; } block->type = BLOCK_TYPE_BOOT; boot_block = block; break; case 'c': if (conf_block) { WARN("only one config block allowed"); break; } block->type = BLOCK_TYPE_CONF; conf_block = block; break; case 'w': if (webp_block) { WARN("only one web block allowed"); break; } block->type = BLOCK_TYPE_WEBP; block->size_hdr = sizeof(struct csys_header); block->size_csum = CSUM_SIZE_8; block->need_file = 0; webp_block = block; break; case 'r': if (code_block) { WARN("only one runtime block allowed"); break; } block->type = BLOCK_TYPE_CODE; block->size_hdr = sizeof(struct csys_header); block->size_csum = CSUM_SIZE_16; code_block = block; break; case 'x': block->type = BLOCK_TYPE_XTRA; break; default: ERR("unknown block type \"%c\"", ch); return ERR_FATAL; } argc = parse_arg(arg, buf, argv); i = 0; p = argv[i++]; if (!is_empty_arg(p)) { block->file_name = strdup(p); if (block->file_name == NULL) { ERR("not enough memory"); return ERR_FATAL; } } else if (block->need_file){ ERR("no file specified in %s", arg); return ERR_FATAL; } if (block->size_hdr) { p = argv[i++]; if (!is_empty_arg(p)) { if (str2u32(p, &block->addr) != 0) { ERR("invalid start address in %s", arg); return ERR_FATAL; } block->addr_set = 1; } } p = argv[i++]; if (!is_empty_arg(p)) { if (str2u32(p, &block->align) != 0) { ERR("invalid alignment value in %s", arg); return ERR_FATAL; } block->align_set = 1; } p = argv[i++]; if (!is_empty_arg(p) && (str2u8(p, &block->padc) != 0)) { ERR("invalid paddig character in %s", arg); return ERR_FATAL; } num_blocks++; return 0;}intprocess_blocks(void){ struct csys_block *block; uint32_t offs = 0; int i; int res; res = 0; /* collecting stats */ for (i = 0; i < num_blocks; i++) { block = &blocks[i]; res = block_stat_file(block); if (res) return res; } /* bootloader */ block = boot_block; if (block) { block->size = board->boot_size; if (block->file_size > board->boot_size) { WARN("boot block is too big"); res = ERR_INVALID_IMAGE; } } offs += board->boot_size; /* configuration data */ block = conf_block; if (block) { block->size = board->conf_size; if (block->file_size > board->conf_size) { WARN("config block is too big"); res = ERR_INVALID_IMAGE; } } offs += board->conf_size; /* webpages */ block = webp_block; if (block) { memcpy(block->sig, board->sig_webp, 4); if (block->addr_set == 0) block->addr = board->addr_webp; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size + block->size_hdr + block->size_csum, block->align) - offs; if (block->size > board->webp_size_max) { WARN("webpages block is too big"); res = ERR_INVALID_IMAGE; } DBG(2,"webpages start at %08x, size=%08x", offs, block->size); offs += block->size; if (offs > board->flash_size) { WARN("webp block is too big"); res = ERR_INVALID_IMAGE; } } /* runtime code */ block = code_block; if (block) { memcpy(code_block->sig, SIG_CSYS, 4); if (block->addr_set == 0) block->addr = board->addr_code; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size + block->size_hdr + block->size_csum, block->align) - offs; DBG(2,"code block start at %08x, size=%08x", offs, block->size); offs += block->size; if (offs > board->flash_size) { WARN("code block is too big"); res = ERR_INVALID_IMAGE; } } for (i = 0; i < num_blocks; i++) { block = &blocks[i]; if (block->type != BLOCK_TYPE_XTRA) continue; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size, block->align) - offs; DBG(2,"file %s start at %08x, size=%08x, align=%08x", block->file_name, offs, block->size, block->align); offs += block->size; if (offs > board->flash_size) { WARN("file %s is too big, size=%d, avail=%d", block->file_name, block->file_size, board->flash_size - offs); res = ERR_INVALID_IMAGE; } } for (i = 0; i < num_blocks; i++) { block = &blocks[i]; block->size_avail = block->size - block->size_hdr - block->size_csum; if (block->size_avail < block->file_size) { WARN("file %s is too big, size=%d, avail=%d", block->file_name, block->file_size, block->size_avail); res = ERR_INVALID_IMAGE; } } return res;}intmain(int argc, char *argv[]){ int optinvalid = 0; /* flag for invalid option */ int c; int res = ERR_FATAL; FILE *outfile; progname=basename(argv[0]); opterr = 0; /* could not print standard getopt error messages */ while ( 1 ) { optinvalid = 0; c = getopt(argc, argv, "b:B:c:dhkr:vw:x:"); if (c == -1) break; switch (c) { case 'b': case 'c': case 'r': case 'x': optinvalid = parse_opt_block(c,optarg); break; case 'w': if (optarg != NULL && *optarg == '-') { /* rollback */ optind--; optarg = NULL; } optinvalid = parse_opt_block(c,optarg); break; case 'd': invalid_causes_error = 0; break; case 'k': keep_invalid_images = 1; break; case 'B': optinvalid = parse_opt_board(c,optarg); break; case 'v': verblevel++; break; case 'h': usage(EXIT_SUCCESS); break; default: optinvalid = 1; break; } if (optinvalid != 0 ){ ERR("invalid option: -%c", optopt); goto out; } } if (board == NULL) { ERR("no board specified"); goto out; } if (optind == argc) { ERR("no output file specified"); goto out; } ofname = argv[optind++]; if (optind < argc) { ERR("invalid option: %s", argv[optind]); goto out; } res = process_blocks(); if (res == ERR_FATAL) goto out; if (res == ERR_INVALID_IMAGE) { if (invalid_causes_error) res = ERR_FATAL; if (keep_invalid_images == 0) { WARN("generation of invalid images disabled", ofname); goto out; } WARN("generating invalid image", ofname); } outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); res = ERR_FATAL; goto out; } if (write_out_blocks(outfile) != 0) { res = ERR_FATAL; goto out_flush; } DBG(1,"Image file %s completed.", ofname);out_flush: fflush(outfile); fclose(outfile); if (res == ERR_FATAL) { unlink(ofname); }out: if (res == ERR_FATAL) return EXIT_FAILURE; return EXIT_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -