X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=tools%2Fzynqmpimage.c;h=f48ac6dbe5056de5b36a1c99695908bfdeeadb41;hb=b31116308c6ebf4fcebacac8c346f603257547e5;hp=3f28eb401d9b439007b98083843a97cdb0a9345c;hpb=3fc304b8d77ce6646d38ae506e9fae74b9975631;p=u-boot diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index 3f28eb401d..f48ac6dbe5 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -6,7 +6,7 @@ * * The following Boot Header format/structures and values are defined in the * following documents: - * * ug1085 ZynqMP TRM (Chapter 9, Table 9-3) + * * ug1085 ZynqMP TRM doc v1.4 (Chapter 11, Table 11-4) * * Expected Header Size = 0x9C0 * Forced as 'little' endian, 32-bit words @@ -99,6 +99,8 @@ struct zynqmp_header { }; static struct zynqmp_header zynqmpimage_header; +static void *dynamic_header; +static FILE *fpmu; static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr) { @@ -181,6 +183,13 @@ static void zynqmpimage_print_header(const void *ptr) printf("Image Size : %lu bytes (%lu bytes packed)\n", (unsigned long)le32_to_cpu(zynqhdr->image_size), (unsigned long)le32_to_cpu(zynqhdr->image_stored_size)); + + if (zynqhdr->pfw_image_length) + printf("PMUFW Size : %lu bytes (%lu bytes packed)\n", + (unsigned long)le32_to_cpu(zynqhdr->pfw_image_length), + (unsigned long)le32_to_cpu( + zynqhdr->total_pfw_image_length)); + printf("Image Load : 0x%08x\n", le32_to_cpu(zynqhdr->image_load)); printf("Checksum : 0x%08x\n", le32_to_cpu(zynqhdr->checksum)); @@ -203,6 +212,8 @@ static void zynqmpimage_print_header(const void *ptr) le32_to_cpu(zynqhdr->register_init[i].address), le32_to_cpu(zynqhdr->register_init[i].data)); } + + free(dynamic_header); } static int zynqmpimage_check_params(struct image_tool_params *params) @@ -234,6 +245,104 @@ static int zynqmpimage_check_image_types(uint8_t type) return EXIT_FAILURE; } +static uint32_t fsize(FILE *fp) +{ + int size, ret, origin; + + origin = ftell(fp); + if (origin < 0) { + fprintf(stderr, "Incorrect file size\n"); + fclose(fp); + exit(2); + } + + ret = fseek(fp, 0L, SEEK_END); + if (ret) { + fprintf(stderr, "Incorrect file SEEK_END\n"); + fclose(fp); + exit(3); + } + + size = ftell(fp); + if (size < 0) { + fprintf(stderr, "Incorrect file size\n"); + fclose(fp); + exit(4); + } + + /* going back */ + ret = fseek(fp, origin, SEEK_SET); + if (ret) { + fprintf(stderr, "Incorrect file SEEK_SET to %d\n", origin); + fclose(fp); + exit(3); + } + + return size; +} + +static void zynqmpimage_pmufw(struct zynqmp_header *zynqhdr, + const char *filename) +{ + uint32_t size; + + /* Setup PMU fw size */ + zynqhdr->pfw_image_length = fsize(fpmu); + zynqhdr->total_pfw_image_length = zynqhdr->pfw_image_length; + + zynqhdr->image_size -= zynqhdr->pfw_image_length; + zynqhdr->image_stored_size -= zynqhdr->total_pfw_image_length; + + /* Read the whole PMUFW to the header */ + size = fread(&zynqhdr->__reserved4[66], 1, + zynqhdr->pfw_image_length, fpmu); + if (size != zynqhdr->pfw_image_length) { + fprintf(stderr, "Cannot read PMUFW file: %s\n", filename); + fclose(fpmu); + exit(1); + } + + fclose(fpmu); +} + +static void zynqmpimage_parse_initparams(struct zynqmp_header *zynqhdr, + const char *filename) +{ + FILE *fp; + struct zynqmp_reginit reginit; + unsigned int reg_count = 0; + int r, err; + struct stat path_stat; + + /* Expect a table of register-value pairs, e.g. "0x12345678 0x4321" */ + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Cannot open initparams file: %s\n", filename); + exit(1); + } + + err = fstat(fileno(fp), &path_stat); + if (err) { + fclose(fp); + return; + } + + if (!S_ISREG(path_stat.st_mode)) { + fclose(fp); + return; + } + + do { + r = fscanf(fp, "%x %x", ®init.address, ®init.data); + if (r == 2) { + zynqhdr->register_init[reg_count] = reginit; + ++reg_count; + } + r = fscanf(fp, "%*[^\n]\n"); /* Skip to next line */ + } while ((r != EOF) && (reg_count < HEADER_REGINITS)); + fclose(fp); +} + static void zynqmpimage_set_header(void *ptr, struct stat *sbuf, int ifd, struct image_tool_params *params) { @@ -250,9 +359,61 @@ static void zynqmpimage_set_header(void *ptr, struct stat *sbuf, int ifd, if (params->eflag) zynqhdr->image_load = cpu_to_le32((uint32_t)params->ep); + /* PMUFW */ + if (fpmu) + zynqmpimage_pmufw(zynqhdr, params->imagename); + + /* User can pass in text file with init list */ + if (strlen(params->imagename2)) + zynqmpimage_parse_initparams(zynqhdr, params->imagename2); + zynqhdr->checksum = zynqmpimage_checksum(zynqhdr); } +static int zynqmpimage_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + struct stat path_stat; + char *filename = params->imagename; + int err; + + /* Handle static case without PMUFW */ + tparams->header_size = sizeof(struct zynqmp_header); + tparams->hdr = (void *)&zynqmpimage_header; + + /* PMUFW name is passed via params->imagename */ + if (strlen(filename) == 0) + return EXIT_SUCCESS; + + fpmu = fopen(filename, "r"); + if (!fpmu) { + fprintf(stderr, "Cannot open PMUFW file: %s\n", filename); + return EXIT_FAILURE; + } + + err = fstat(fileno(fpmu), &path_stat); + if (err) { + fclose(fpmu); + fpmu = NULL; + return EXIT_FAILURE; + } + + if (!S_ISREG(path_stat.st_mode)) { + fclose(fpmu); + fpmu = NULL; + return EXIT_FAILURE; + } + + /* Increase header size by PMUFW file size */ + tparams->header_size += fsize(fpmu); + + /* Allocate buffer with space for PMUFW */ + dynamic_header = calloc(1, tparams->header_size); + tparams->hdr = dynamic_header; + + return EXIT_SUCCESS; +} + U_BOOT_IMAGE_TYPE( zynqmpimage, "Xilinx ZynqMP Boot Image support", @@ -265,5 +426,5 @@ U_BOOT_IMAGE_TYPE( NULL, zynqmpimage_check_image_types, NULL, - NULL + zynqmpimage_vrec_header );