예제 #1
0
static int
kwboot_img_patch_hdr(void *img, size_t size)
{
	int rc;
	struct main_hdr_v1 *hdr;
	uint8_t csum;
	size_t hdrsz = sizeof(*hdr);
	int image_ver;

	rc = -1;
	hdr = img;

	if (size < hdrsz) {
		errno = EINVAL;
		goto out;
	}

	image_ver = image_version(img);
	if (image_ver < 0) {
		fprintf(stderr, "Invalid image header version\n");
		errno = EINVAL;
		goto out;
	}

	if (image_ver == 0)
		hdrsz = sizeof(*hdr);
	else
		hdrsz = KWBHEADER_V1_SIZE(hdr);

	csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checksum;
	if (csum != hdr->checksum) {
		errno = EINVAL;
		goto out;
	}

	if (hdr->blockid == IBR_HDR_UART_ID) {
		rc = 0;
		goto out;
	}

	hdr->blockid = IBR_HDR_UART_ID;

	/*
	 * Subtract mkimage header size from destination address
	 * as this header is not expected by the Marvell BootROM.
	 * This way, the execution address is identical to the
	 * one the image is compiled for (TEXT_BASE).
	 */
	hdr->destaddr = hdr->destaddr - sizeof(struct image_header);

	if (image_ver == 0) {
		struct main_hdr_v0 *hdr_v0 = img;

		hdr_v0->nandeccmode = IBR_HDR_ECC_DISABLED;
		hdr_v0->nandpagesize = 0;

		hdr_v0->srcaddr = hdr_v0->ext
			? sizeof(struct kwb_header)
			: sizeof(*hdr_v0);
	}

	hdr->checksum = kwboot_img_csum8(hdr, hdrsz) - csum;

	rc = 0;
out:
	return rc;
}
예제 #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);
}