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; }
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); }