Пример #1
0
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;
}
Пример #2
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);
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
0
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;
}
Пример #10
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    = 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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}