Ejemplo n.º 1
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;
		}

		/* payload size must be multiple of 32b */
		payloadsz = 4 * ((s.st_size + 3)/4);
	}

	/* 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;
}
Ejemplo n.º 2
0
static int image_extract_v1(void *fdimap, const char *output, FILE *focfg)
{
	struct main_hdr_v1 *main_hdr = fdimap;
	struct opt_hdr_v1 *opt_hdr;
	const char *boot_mode_name;
	int headersz = KWBHEADER_V1_SIZE(main_hdr);
	int hasheaders;
	uint8_t cksum;
	int opthdrid;

	/*
	 * Verify the checkum. We have to substract the checksum
	 * itself, because when the checksum is calculated, the
	 * checksum field is 0.
	 */
	cksum = image_checksum8(main_hdr, headersz);
	cksum -= main_hdr->checksum;

	if (cksum != main_hdr->checksum) {
		fprintf(stderr,
			"Invalid main header checksum: 0x%08x vs. 0x%08x\n",
			cksum, main_hdr->checksum);
		return -1;
	}

	/* First, take care of the main header */
	boot_mode_name = image_boot_mode_name(main_hdr->blockid);
	if (!boot_mode_name) {
		fprintf(stderr, "Invalid boot ID: 0x%x\n",
			main_hdr->blockid);
		return -1;
	}

	fprintf(focfg, "VERSION 1\n");
	fprintf(focfg, "BOOT_FROM %s\n", boot_mode_name);
	fprintf(focfg, "DESTADDR %08x\n", main_hdr->destaddr);
	fprintf(focfg, "EXECADDR %08x\n", main_hdr->execaddr);
	fprintf(focfg, "NAND_BLKSZ %08x\n",
		main_hdr->nandblocksize * 64 * 1024);
	fprintf(focfg, "NAND_BADBLK_LOCATION %02x\n",
		main_hdr->nandbadblklocation);

	hasheaders = main_hdr->ext;
	opt_hdr = fdimap + sizeof(struct main_hdr_v1);
	opthdrid = 0;

	/* Then, go through all the extension headers */
	while (hasheaders) {
		int opthdrsz = KWBHEADER_V1_SIZE(opt_hdr);

		switch (opt_hdr->headertype) {
		case OPT_HDR_V1_BINARY_TYPE:
			image_extract_binary_hdr_v1(opt_hdr->data, output,
						    focfg, opthdrid,
						    opthdrsz -
						    sizeof(struct opt_hdr_v1));
			break;
		case OPT_HDR_V1_SECURE_TYPE:
		case OPT_HDR_V1_REGISTER_TYPE:
			fprintf(stderr,
				"Support for header type 0x%x not implemented\n",
				opt_hdr->headertype);
			exit(1);
			break;
		default:
			fprintf(stderr, "Invalid header type 0x%x\n",
				opt_hdr->headertype);
			exit(1);
		}

		/*
		 * The first byte of the last double word of the
		 * current header indicates whether there is a next
		 * header or not.
		 */
		hasheaders = ((char *)opt_hdr)[opthdrsz - 4];

		/* Move to the next header */
		opt_hdr = ((void *)opt_hdr) + opthdrsz;
		opthdrid++;
	}

	/* Finally, handle the image itself */
	fprintf(focfg, "PAYLOAD %s/payload\n", output);
	return image_extract_payload(fdimap + main_hdr->srcaddr,
				     main_hdr->blocksize - 4,
				     output);
}
Ejemplo n.º 3
0
static int image_extract_v0(void *fdimap, const char *output, FILE *focfg)
{
	struct main_hdr_v0 *main_hdr = fdimap;
	struct ext_hdr_v0 *ext_hdr;
	const char *boot_mode_name;
	uint32_t *img_checksum;
	size_t payloadsz;
	int cksum, i;

	/*
	 * Verify checksum. When calculating the header, discard the
	 * last byte of the header, which itself contains the
	 * checksum.
	 */
	cksum = image_checksum8(main_hdr, sizeof(struct main_hdr_v0)-1);
	if (cksum != main_hdr->checksum) {
		fprintf(stderr,
			"Invalid main header checksum: 0x%08x vs. 0x%08x\n",
			cksum, main_hdr->checksum);
		return -1;
	}

	boot_mode_name = image_boot_mode_name(main_hdr->blockid);
	if (!boot_mode_name) {
		fprintf(stderr, "Invalid boot ID: 0x%x\n",
			main_hdr->blockid);
		return -1;
	}

	fprintf(focfg, "VERSION 0\n");
	fprintf(focfg, "BOOT_FROM %s\n", boot_mode_name);
	fprintf(focfg, "DESTADDR %08x\n", main_hdr->destaddr);
	fprintf(focfg, "EXECADDR %08x\n", main_hdr->execaddr);

	if (!strcmp(boot_mode_name, "nand")) {
		const char *nand_ecc_mode =
			image_nand_ecc_mode_name(main_hdr->nandeccmode);
		fprintf(focfg, "NAND_ECCMODE %s\n",
			nand_ecc_mode);
		fprintf(focfg, "NAND_PAGESZ %08x\n",
			main_hdr->nandpagesize);
	}

	/* No extension header, we're done */
	if (!main_hdr->ext)
		return 0;

	ext_hdr = fdimap + sizeof(struct main_hdr_v0);

	for (i = 0; i < EXT_HDR_V0_REG_COUNT; i++) {
		if (ext_hdr->rcfg[i].raddr == 0 &&
		    ext_hdr->rcfg[i].rdata == 0)
			break;

		fprintf(focfg, "DATA %08x %08x\n",
			ext_hdr->rcfg[i].raddr,
			ext_hdr->rcfg[i].rdata);
	}

	/* The image is concatenated with a 32 bits checksum */
	payloadsz = main_hdr->blocksize - sizeof(uint32_t);
	img_checksum = (uint32_t *) (fdimap + main_hdr->srcaddr + payloadsz);

	if (*img_checksum != image_checksum32(fdimap + main_hdr->srcaddr,
					      payloadsz)) {
		fprintf(stderr, "The image checksum does not match\n");
		return -1;
	}

	/* Finally, handle the image itself */
	fprintf(focfg, "PAYLOAD %s/payload\n", output);
	return image_extract_payload(fdimap + main_hdr->srcaddr,
				     payloadsz, output);
}
Ejemplo n.º 4
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;
		binhdrsz = ALIGN_SUP(binhdrsz, 32);
		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;
}
Ejemplo n.º 5
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 = payloadsz + sizeof(uint32_t) - headersz;
	main_hdr->srcaddr   = headersz;
	main_hdr->ext       = has_ext;
	main_hdr->destaddr  = params->addr;
	main_hdr->execaddr  = 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 = 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));
	}

	*imagesz = headersz;
	return image;
}
Ejemplo n.º 6
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 += ALIGN_SUP(s.st_size, 4) +
			12 + 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;
		}

		/* payload size must be multiple of 32b */
		payloadsz = ALIGN_SUP(s.st_size, 4);
	}

	/* 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 + 2) * sizeof(unsigned int) +
			ALIGN_SUP(s.st_size, 4);
		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);

		if (s.st_size)
			ret = fread(cur, s.st_size, 1, bin);
		else
			ret = 1;

		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
		 */
		*((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;
}