static int image_override_bootmedia(struct image_cfg_element *image_cfg, int *cfgn, const char *bootmedia) { struct image_cfg_element *e; int bootfrom; int cfgi = *cfgn; if (!bootmedia) return 0; bootfrom = image_boot_mode_id(bootmedia); if (!bootfrom) { fprintf(stderr, "Invalid boot media '%s'\n", bootmedia); return -1; } e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_BOOT_FROM); if (e) { e->bootfrom = bootfrom; return 0; } image_cfg[cfgi].type = IMAGE_CFG_BOOT_FROM; image_cfg[cfgi].bootfrom = bootfrom; cfgi++; *cfgn = cfgi; return 0; }
static size_t image_headersz_v1(struct image_tool_params *params, int *hasext) { struct image_cfg_element *binarye; size_t headersz; int ret; /* * Calculate the size of the header and the size of the * payload */ headersz = sizeof(struct main_hdr_v1); if (image_count_options(IMAGE_CFG_BINARY) > 1) { fprintf(stderr, "More than one binary blob, not supported\n"); return 0; } if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) { fprintf(stderr, "More than one payload, not possible\n"); return 0; } binarye = image_find_option(IMAGE_CFG_BINARY); if (binarye) { struct stat s; ret = stat(binarye->binary.file, &s); if (ret < 0) { char cwd[PATH_MAX]; char *dir = cwd; memset(cwd, 0, sizeof(cwd)); if (!getcwd(cwd, sizeof(cwd))) { dir = "current working directory"; perror("getcwd() failed"); } fprintf(stderr, "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" "image for your board. See 'kwbimage -x' to extract it from an existing image.\n", binarye->binary.file, dir); return 0; } headersz += s.st_size + binarye->binary.nargs * sizeof(unsigned int); if (hasext) *hasext = 1; } /* * The payload should be aligned on some reasonable * boundary */ return ALIGN_SUP(headersz, 4096); }
static int image_get_version(void) { struct image_cfg_element *e; e = image_find_option(IMAGE_CFG_VERSION); if (!e) return -1; return e->version; }
static int image_get_version(struct image_cfg_element *image_cfg, int cfgn) { struct image_cfg_element *e; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_VERSION); if (!e) return -1; return e->version; }
static int image_override_execaddr(struct image_cfg_element *image_cfg, int *cfgn, uint32_t execaddr) { struct image_cfg_element *e; int cfgi = *cfgn; if (execaddr == ADDR_INVALID) return 0; e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_EXEC_ADDR); if (e) { e->execaddr = execaddr; return 0; } image_cfg[cfgi].type = IMAGE_CFG_EXEC_ADDR; image_cfg[cfgi].execaddr = execaddr; cfgi++; *cfgn = cfgi; return 0; }
static int image_override_payload(struct image_cfg_element *image_cfg, int *cfgn, const char *payload) { struct image_cfg_element *e; int cfgi = *cfgn; if (!payload) return 0; e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_PAYLOAD); if (e) { e->payload = payload; return 0; } image_cfg[cfgi].type = IMAGE_CFG_PAYLOAD; image_cfg[cfgi].payload = payload; cfgi++; *cfgn = cfgi; return 0; }
static int image_override_binary(struct image_cfg_element *image_cfg, int *cfgn, char *binary) { struct image_cfg_element *e; int cfgi = *cfgn; if (!binary) return 0; e = image_find_option(image_cfg, *cfgn, IMAGE_CFG_BINARY); if (e) { e->binary.file = binary; return 0; } image_cfg[cfgi].type = IMAGE_CFG_BINARY; image_cfg[cfgi].binary.file = binary; image_cfg[cfgi].binary.nargs = 0; cfgi++; *cfgn = cfgi; return 0; }
static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, int payloadsz) { struct image_cfg_element *e, *binarye; struct main_hdr_v1 *main_hdr; size_t headersz; void *image, *cur; int hasext = 0; int ret; /* * Calculate the size of the header and the size of the * payload */ headersz = image_headersz_v1(params, &hasext); if (headersz == 0) return NULL; image = malloc(headersz); if (!image) { fprintf(stderr, "Cannot allocate memory for image\n"); return NULL; } memset(image, 0, headersz); cur = main_hdr = image; cur += sizeof(struct main_hdr_v1); /* Fill the main header */ main_hdr->blocksize = cpu_to_le32(payloadsz - headersz + sizeof(uint32_t)); main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF); main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; main_hdr->destaddr = cpu_to_le32(params->addr); main_hdr->execaddr = cpu_to_le32(params->ep); main_hdr->srcaddr = cpu_to_le32(headersz); main_hdr->ext = hasext; main_hdr->version = 1; e = image_find_option(IMAGE_CFG_BOOT_FROM); if (e) main_hdr->blockid = e->bootfrom; e = image_find_option(IMAGE_CFG_NAND_BLKSZ); if (e) main_hdr->nandblocksize = e->nandblksz / (64 * 1024); e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); if (e) main_hdr->nandbadblklocation = e->nandbadblklocation; e = image_find_option(IMAGE_CFG_BAUDRATE); if (e) main_hdr->options = baudrate_to_option(e->baudrate); e = image_find_option(IMAGE_CFG_DEBUG); if (e) main_hdr->flags = e->debug ? 0x1 : 0; binarye = image_find_option(IMAGE_CFG_BINARY); if (binarye) { struct opt_hdr_v1 *hdr = cur; uint32_t *args; size_t binhdrsz; struct stat s; int argi; FILE *bin; hdr->headertype = OPT_HDR_V1_BINARY_TYPE; bin = fopen(binarye->binary.file, "r"); if (!bin) { fprintf(stderr, "Cannot open binary file %s\n", binarye->binary.file); return NULL; } fstat(fileno(bin), &s); binhdrsz = sizeof(struct opt_hdr_v1) + (binarye->binary.nargs + 2) * sizeof(uint32_t) + s.st_size; /* * The size includes the binary image size, rounded * up to a 4-byte boundary. Plus 4 bytes for the * next-header byte and 3-byte alignment at the end. */ binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4; hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF); hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; cur += sizeof(struct opt_hdr_v1); args = cur; *args = cpu_to_le32(binarye->binary.nargs); args++; for (argi = 0; argi < binarye->binary.nargs; argi++) args[argi] = cpu_to_le32(binarye->binary.args[argi]); cur += (binarye->binary.nargs + 1) * sizeof(uint32_t); ret = fread(cur, s.st_size, 1, bin); if (ret != 1) { fprintf(stderr, "Could not read binary image %s\n", binarye->binary.file); return NULL; } fclose(bin); cur += ALIGN_SUP(s.st_size, 4); /* * For now, we don't support more than one binary * header, and no other header types are * supported. So, the binary header is necessarily the * last one */ *((uint32_t *)cur) = 0x00000000; cur += sizeof(uint32_t); } /* Calculate and set the header checksum */ main_hdr->checksum = image_checksum8(main_hdr, headersz); *imagesz = headersz; return image; }
static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, int payloadsz) { struct image_cfg_element *e; size_t headersz; struct main_hdr_v0 *main_hdr; struct ext_hdr_v0 *ext_hdr; void *image; int has_ext = 0; /* * Calculate the size of the header and the size of the * payload */ headersz = sizeof(struct main_hdr_v0); if (image_count_options(IMAGE_CFG_DATA) > 0) { has_ext = 1; headersz += sizeof(struct ext_hdr_v0); } if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) { fprintf(stderr, "More than one payload, not possible\n"); return NULL; } image = malloc(headersz); if (!image) { fprintf(stderr, "Cannot allocate memory for image\n"); return NULL; } memset(image, 0, headersz); main_hdr = image; /* Fill in the main header */ main_hdr->blocksize = cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz); main_hdr->srcaddr = cpu_to_le32(headersz); main_hdr->ext = has_ext; main_hdr->destaddr = cpu_to_le32(params->addr); main_hdr->execaddr = cpu_to_le32(params->ep); e = image_find_option(IMAGE_CFG_BOOT_FROM); if (e) main_hdr->blockid = e->bootfrom; e = image_find_option(IMAGE_CFG_NAND_ECC_MODE); if (e) main_hdr->nandeccmode = e->nandeccmode; e = image_find_option(IMAGE_CFG_NAND_PAGESZ); if (e) main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz); main_hdr->checksum = image_checksum8(image, sizeof(struct main_hdr_v0)); /* Generate the ext header */ if (has_ext) { int cfgi, datai; ext_hdr = image + sizeof(struct main_hdr_v0); ext_hdr->offset = cpu_to_le32(0x40); for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) { e = &image_cfg[cfgi]; if (e->type != IMAGE_CFG_DATA) continue; ext_hdr->rcfg[datai].raddr = cpu_to_le32(e->regdata.raddr); ext_hdr->rcfg[datai].rdata = cpu_to_le32(e->regdata.rdata); datai++; } ext_hdr->checksum = image_checksum8(ext_hdr, sizeof(struct ext_hdr_v0)); } *imagesz = headersz; return image; }
static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, int payloadsz) { struct image_cfg_element *e, *binarye; struct main_hdr_v1 *main_hdr; size_t headersz; void *image, *cur; int hasext = 0; int ret; /* * Calculate the size of the header and the size of the * payload */ headersz = image_headersz_v1(params, &hasext); if (headersz == 0) return NULL; image = malloc(headersz); if (!image) { fprintf(stderr, "Cannot allocate memory for image\n"); return NULL; } memset(image, 0, headersz); cur = main_hdr = image; cur += sizeof(struct main_hdr_v1); /* Fill the main header */ main_hdr->blocksize = payloadsz - headersz + sizeof(uint32_t); main_hdr->headersz_lsb = headersz & 0xFFFF; main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; main_hdr->destaddr = params->addr; main_hdr->execaddr = params->ep; main_hdr->srcaddr = headersz; main_hdr->ext = hasext; main_hdr->version = 1; e = image_find_option(IMAGE_CFG_BOOT_FROM); if (e) main_hdr->blockid = e->bootfrom; e = image_find_option(IMAGE_CFG_NAND_BLKSZ); if (e) main_hdr->nandblocksize = e->nandblksz / (64 * 1024); e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); if (e) main_hdr->nandbadblklocation = e->nandbadblklocation; binarye = image_find_option(IMAGE_CFG_BINARY); if (binarye) { struct opt_hdr_v1 *hdr = cur; unsigned int *args; size_t binhdrsz; struct stat s; int argi; FILE *bin; hdr->headertype = OPT_HDR_V1_BINARY_TYPE; bin = fopen(binarye->binary.file, "r"); if (!bin) { fprintf(stderr, "Cannot open binary file %s\n", binarye->binary.file); return NULL; } fstat(fileno(bin), &s); binhdrsz = sizeof(struct opt_hdr_v1) + (binarye->binary.nargs + 1) * sizeof(unsigned int) + s.st_size; hdr->headersz_lsb = binhdrsz & 0xFFFF; hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; cur += sizeof(struct opt_hdr_v1); args = cur; *args = binarye->binary.nargs; args++; for (argi = 0; argi < binarye->binary.nargs; argi++) args[argi] = binarye->binary.args[argi]; cur += (binarye->binary.nargs + 1) * sizeof(unsigned int); ret = fread(cur, s.st_size, 1, bin); if (ret != 1) { fprintf(stderr, "Could not read binary image %s\n", binarye->binary.file); return NULL; } fclose(bin); cur += s.st_size; /* * For now, we don't support more than one binary * header, and no other header types are * supported. So, the binary header is necessarily the * last one */ *((unsigned char *)cur) = 0; cur += sizeof(uint32_t); } /* Calculate and set the header checksum */ main_hdr->checksum = image_checksum8(main_hdr, headersz); *imagesz = headersz; return image; }
static void *image_create_v1(struct image_cfg_element *image_cfg, int cfgn, const char *output, size_t *imagesz) { struct image_cfg_element *e, *payloade, *binarye; struct main_hdr_v1 *main_hdr; size_t headersz, payloadsz, totalsz; void *image, *cur; int hasext = 0; int ret; /* Calculate the size of the header and the size of the * payload */ headersz = sizeof(struct main_hdr_v1); payloadsz = 0; if (image_count_options(image_cfg, cfgn, IMAGE_CFG_BINARY) > 1) { fprintf(stderr, "More than one binary blob, not supported\n"); return NULL; } if (image_count_options(image_cfg, cfgn, IMAGE_CFG_PAYLOAD) > 1) { fprintf(stderr, "More than one payload, not possible\n"); return NULL; } binarye = image_find_option(image_cfg, cfgn, IMAGE_CFG_BINARY); if (binarye) { struct stat s; ret = stat(binarye->binary.file, &s); if (ret < 0) { char *cwd = get_current_dir_name(); fprintf(stderr, "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n" "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n" "image for your board. See 'kwbimage -x' to extract it from an existing image.\n", binarye->binary.file, cwd); free(cwd); return NULL; } headersz += s.st_size + binarye->binary.nargs * sizeof(unsigned int); hasext = 1; } payloade = image_find_option(image_cfg, cfgn, IMAGE_CFG_PAYLOAD); if (payloade) { struct stat s; ret = stat(payloade->payload, &s); if (ret < 0) { fprintf(stderr, "Cannot stat payload file %s\n", payloade->payload); return NULL; } payloadsz = s.st_size; } /* The payload should be aligned on some reasonable * boundary */ headersz = ALIGN_SUP(headersz, 4096); /* The total size includes the headers, the payload, and the * 32 bits checksum at the end of the payload */ totalsz = headersz + payloadsz + sizeof(uint32_t); image = malloc(totalsz); if (!image) { fprintf(stderr, "Cannot allocate memory for image\n"); return NULL; } memset(image, 0, totalsz); cur = main_hdr = image; cur += sizeof(struct main_hdr_v1); /* Fill the main header */ main_hdr->blocksize = payloadsz + sizeof(uint32_t); main_hdr->headersz_lsb = headersz & 0xFFFF; main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; main_hdr->srcaddr = headersz; main_hdr->ext = hasext; main_hdr->version = 1; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM); if (e) main_hdr->blockid = e->bootfrom; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR); if (e) main_hdr->destaddr = e->dstaddr; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR); if (e) main_hdr->execaddr = e->execaddr; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_BLKSZ); if (e) main_hdr->nandblocksize = e->nandblksz / (64 * 1024); e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_BADBLK_LOCATION); if (e) main_hdr->nandbadblklocation = e->nandbadblklocation; if (binarye) { struct opt_hdr_v1 *hdr = cur; unsigned int *args; size_t binhdrsz; struct stat s; int argi; FILE *bin; hdr->headertype = OPT_HDR_V1_BINARY_TYPE; bin = fopen(binarye->binary.file, "r"); if (!bin) { fprintf(stderr, "Cannot open binary file %s\n", binarye->binary.file); return NULL; } fstat(fileno(bin), &s); binhdrsz = sizeof(struct opt_hdr_v1) + (binarye->binary.nargs + 1) * sizeof(unsigned int) + s.st_size; hdr->headersz_lsb = binhdrsz & 0xFFFF; hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16; cur += sizeof(struct opt_hdr_v1); args = cur; *args = binarye->binary.nargs; args++; for (argi = 0; argi < binarye->binary.nargs; argi++) args[argi] = binarye->binary.args[argi]; cur += (binarye->binary.nargs + 1) * sizeof(unsigned int); ret = fread(cur, s.st_size, 1, bin); if (ret != 1) { fprintf(stderr, "Could not read binary image %s\n", binarye->binary.file); return NULL; } fclose(bin); cur += s.st_size; /* * For now, we don't support more than one binary * header, and no other header types are * supported. So, the binary header is necessarily the * last one */ *((unsigned char *) cur) = 0; cur += sizeof(uint32_t); } /* Calculate and set the header checksum */ main_hdr->checksum = image_checksum8(main_hdr, headersz); if (payloade) { ret = image_create_payload(image + headersz, payloadsz, payloade->payload); if (ret < 0) return NULL; } *imagesz = totalsz; return image; }
static void *image_create_v0(struct image_cfg_element *image_cfg, int cfgn, const char *output, size_t *imagesz) { struct image_cfg_element *e, *payloade; size_t headersz, payloadsz, totalsz; struct main_hdr_v0 *main_hdr; struct ext_hdr_v0 *ext_hdr; void *image; int has_ext = 0; int ret; /* Calculate the size of the header and the size of the * payload */ headersz = sizeof(struct main_hdr_v0); payloadsz = 0; if (image_count_options(image_cfg, cfgn, IMAGE_CFG_DATA) > 0) { has_ext = 1; headersz += sizeof(struct ext_hdr_v0); } if (image_count_options(image_cfg, cfgn, IMAGE_CFG_PAYLOAD) > 1) { fprintf(stderr, "More than one payload, not possible\n"); return NULL; } payloade = image_find_option(image_cfg, cfgn, IMAGE_CFG_PAYLOAD); if (payloade) { struct stat s; int ret; ret = stat(payloade->payload, &s); if (ret < 0) { fprintf(stderr, "Cannot stat payload file %s\n", payloade->payload); return NULL; } payloadsz = s.st_size; } /* Headers, payload and 32-bits checksum */ totalsz = headersz + payloadsz + sizeof(uint32_t); image = malloc(totalsz); if (!image) { fprintf(stderr, "Cannot allocate memory for image\n"); return NULL; } memset(image, 0, totalsz); main_hdr = image; /* Fill in the main header */ main_hdr->blocksize = payloadsz + sizeof(uint32_t); main_hdr->srcaddr = headersz; main_hdr->ext = has_ext; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM); if (e) main_hdr->blockid = e->bootfrom; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR); if (e) main_hdr->destaddr = e->dstaddr; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR); if (e) main_hdr->execaddr = e->execaddr; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_ECC_MODE); if (e) main_hdr->nandeccmode = e->nandeccmode; e = image_find_option(image_cfg, cfgn, IMAGE_CFG_NAND_PAGESZ); if (e) main_hdr->nandpagesize = e->nandpagesz; main_hdr->checksum = image_checksum8(image, sizeof(struct main_hdr_v0)); /* Generate the ext header */ if (has_ext) { int cfgi, datai; ext_hdr = image + sizeof(struct main_hdr_v0); ext_hdr->offset = 0x40; for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) { e = &image_cfg[cfgi]; if (e->type != IMAGE_CFG_DATA) continue; ext_hdr->rcfg[datai].raddr = e->regdata.raddr; ext_hdr->rcfg[datai].rdata = e->regdata.rdata; datai++; } ext_hdr->checksum = image_checksum8(ext_hdr, sizeof(struct ext_hdr_v0)); } if (payloade) { ret = image_create_payload(image + headersz, payloadsz, payloade->payload); if (ret < 0) return NULL; } *imagesz = totalsz; return image; }
static int image_create(const char *input, const char *output, const char *payload, const char *bootmedia, uint32_t dstaddr, uint32_t execaddr, int verbose) { struct image_cfg_element *image_cfg; FILE *fcfg, *outputimg; void *image = NULL; int version; size_t imagesz; int cfgn; int ret; fcfg = fopen(input, "r"); if (!fcfg) { fprintf(stderr, "Could not open input file %s\n", input); return -1; } image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); if (!image_cfg) { fprintf(stderr, "Cannot allocate memory\n"); fclose(fcfg); return -1; } memset(image_cfg, 0, IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element)); rewind(fcfg); ret = image_create_config_parse(fcfg, image_cfg, &cfgn); if (ret) { free(image_cfg); return -1; } image_override_payload(image_cfg, &cfgn, payload); image_override_bootmedia(image_cfg, &cfgn, bootmedia); image_override_dstaddr(image_cfg, &cfgn, dstaddr); image_override_execaddr(image_cfg, &cfgn, execaddr); if (!image_find_option(image_cfg, cfgn, IMAGE_CFG_BOOT_FROM) || !image_find_option(image_cfg, cfgn, IMAGE_CFG_DEST_ADDR) || !image_find_option(image_cfg, cfgn, IMAGE_CFG_EXEC_ADDR)) { fprintf(stderr, "Missing information (either boot media, exec addr or dest addr)\n"); free(image_cfg); return -1; } if (verbose) image_dump_config(image_cfg, cfgn); version = image_get_version(image_cfg, cfgn); if (version == 0) image = image_create_v0(image_cfg, cfgn, output, &imagesz); else if (version == 1) image = image_create_v1(image_cfg, cfgn, output, &imagesz); else if (version == -1) { fprintf(stderr, "File %s does not have the VERSION field\n", input); free(image_cfg); return -1; } if (!image) { fprintf(stderr, "Could not create image\n"); free(image_cfg); return -1; } free(image_cfg); outputimg = fopen(output, "w"); if (!outputimg) { fprintf(stderr, "Cannot open output image %s for writing\n", output); free(image); return -1; } ret = fwrite(image, imagesz, 1, outputimg); if (ret != 1) { fprintf(stderr, "Cannot write to output image %s\n", output); fclose(outputimg); free(image); return -1; } fclose(outputimg); free(image); return 0; }