long cfg_get_number(const char *name, group_t *head) { variable_t *var = cfg_find_var(name, head); if (var && var->type == VT_NUMBER) return var->number; return 0; }
static variable_t* parse_expr(char **ptr, variable_t *var, group_t *head) { char value[MAXLINELEN]; char *buf = value; size_t buflen = sizeof(value); int is_str = false; char *p = *ptr; long number; do { skip_whitespace(&p); if (!is_str && isdigit(*p)) { char *end; /* parse number */ number = strtol(p, &end, 0); p = end; } else if (*p == '"' || *p == '\'') { char *s = parse_string(&p, buf, buflen); buf += strlen(s); buflen -= strlen(s); is_str = true; } else if (isalpha(*p)) { /* parse identifier */ char ident[MAXIDLEN]; variable_t *var; parse_identifier(&p, ident, sizeof(ident)); var = cfg_find_var(ident, head); if (var == NULL || var->type == VT_STRING) { const char *str = var ? var->str : ident; strncpy(buf, str, buflen); buflen -= strlen(str); buf += strlen(str); is_str = true; } else if (var && var->type == VT_NUMBER) { buflen -= snprintf(buf, buflen, "0x%lx", var->number); } else { fprintf(stderr, "%s:%d: listitem used in expression!\n", __func__, lineno); break; } } else { fprintf(stderr, "%s:%d: unknown token!\n", __func__, lineno); break; } skip_whitespace(&p); if (is_str && *p == '.' && p[1] == '.') { p += 2; } else { break; } } while( true ); if (is_str) { var->type = VT_STRING; var->str = strdup(value); } else { var->type = VT_NUMBER; var->number = number; } *ptr = p; return var; }
static int pack_image(const char *indn, const char *outfn) { struct imagewty_header *header; group_t *head, *filelist; uint32_t i, num_files; variable_t *var; FILE *cfp, *ofp; void *p; /* try to open image configuration */ cfp = dir_fopen(indn, "image.cfg", "r"); if (cfp == NULL) { fprintf(stderr, "Error: unable to open %s/%s!\n", indn, "image.cfg"); return -ENOENT; } ofp = fopen(outfn, "wb"); if (ofp == NULL) { fprintf(stderr, "Error: could not create image file %s!\n", outfn); fclose(cfp); return -ENOENT; } /* file is there, now try to load it */ head = cfg_load(cfp); fclose(cfp); if (head == NULL) { fprintf(stderr, "Error: failed to parse %s/%s!\n", indn, "image.cfg"); return -EINVAL; } /* Got configuration, time to start packing it all up! */ var = cfg_find_var("filelist", head); if (var == NULL || var->type != VT_STRING) { fprintf(stderr, "Error: Unable to find filelist string " "variable in configuration!\n"); cfg_free(head); return -EINVAL; } filelist = cfg_find_group(var->str, head); if (filelist == NULL) { fprintf(stderr, "Error: unable to find group %s!\n", var->str); cfg_free(head); return -EINVAL; } num_files = cfg_count_vars(filelist); if (!num_files) { fprintf(stderr, "Error: no files to pack found in configuration!\n"); cfg_free(head); return -EINVAL; } p = malloc(1024 + num_files * 1024); if (p == NULL) { fprintf(stderr, "Error: failed to allocate memory for image!\n"); cfg_free(head); return -ENOMEM; } /* Initialize image file header */ memset(p, 0, 1024 + num_files * 1024); header = p; memcpy(header->magic, IMAGEWTY_MAGIC, sizeof(header->magic)); header->header_version = 0x0100; header->header_size = 0x50; /* should be 0x60 for version == 0x0300 */ header->ram_base = 0x04D00000; header->version = cfg_get_number("version", head); header->image_size = 0; /* this will be filled in later on */ header->image_header_size = 1024; header->v1.pid = cfg_get_number("pid", head); header->v1.vid = cfg_get_number("vid", head); header->v1.hardware_id = cfg_get_number("hardwareid", head); header->v1.firmware_id = cfg_get_number("firmwareid", head); header->v1.val1 = 1; header->v1.val1024 = 1024; header->v1.num_files = num_files; header->v1.num_files = cfg_count_vars(filelist); header->v1.val1024_2 = 1024; /* Setup file headers */ { uint32_t offset = (num_files +1) * 1024; struct imagewty_file_header *fheaders; variable_t *var; fheaders = (struct imagewty_file_header*) (p + 1024); for(var=filelist->vars; var; var=var->next) { variable_t *v, *fn = NULL, *mt = NULL, *st = NULL; uint32_t size; FILE *fp; for (v=var->items; v; v=v->next) { if (v->type != VT_STRING) continue; if (strcmp(v->name, "filename") == 0) fn = v; else if (strcmp(v->name, "maintype") == 0) mt = v; else if (strcmp(v->name, "subtype") == 0) st = v; } if (!fn || !mt || !st) { fprintf(stderr, "Error: incomplete filelist item!\n"); return -EINVAL; } fheaders->filename_len = IMAGEWTY_FHDR_FILENAME_LEN; fheaders->total_header_size = 1024; strcpy((char*)fheaders->v1.filename, fn->str); strcpy((char*)fheaders->maintype, mt->str); strcpy((char*)fheaders->subtype, st->str); fp = dir_fopen(indn, fn->str, "rb"); if (fp) { fseek(fp, 0, SEEK_END); size = ftell(fp); fclose(fp); } else { fprintf(stderr, "Error: unable to read file '%s'!\n", fn->str); continue; } fheaders->v1.offset = offset; fheaders->v1.stored_length = fheaders->v1.original_length = size; if (fheaders->v1.stored_length & 0x1FF) { fheaders->v1.stored_length &= ~0x1FF; fheaders->v1.stored_length += 0x200; } offset += fheaders->v1.stored_length; fheaders = (struct imagewty_file_header*) ((uint8_t*)fheaders + 1024); } /* We now know the total size of the file; patch it into the main header */ if (offset & 0xFF) offset = (offset & 0xFF) + 0x100; header->image_size = offset; } /* Now we have all headers setup in memory, time to write out the image file */ fwrite(p, 1024, num_files +1, ofp); /* now write the file content too */ for (i = 1; i <= num_files; i++) { struct imagewty_file_header *h = (struct imagewty_file_header*)(p + i * 1024); FILE *fp = dir_fopen(indn, h->v1.filename, "rb"); if (fp != NULL) { char buf[512]; size_t size = 0; while(!feof(fp)) { size_t bytesread = fread(buf, 1, 512, fp); if (bytesread) { if (bytesread & 0x1ff) bytesread = (bytesread & ~0x1ff) + 0x200; if (flag_encryption_enabled) rc6_encrypt_inplace(buf, bytesread, &filecontent_ctx); fwrite(buf, 1, bytesread, ofp); } size += bytesread; } fclose(fp); } } /* Headers no longer used; encrypt and write if requested */ if (flag_encryption_enabled) { void *curr = rc6_encrypt_inplace(p, 1024, &header_ctx); rc6_encrypt_inplace(curr, num_files * 1024, &fileheaders_ctx); rewind(ofp); fwrite(p, 1024, num_files +1, ofp); } fclose(ofp); /* Done, free configuration, no longer needed */ cfg_free(head); return 0; }