Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright Heinrich Schuchardt <heinrich.schuchardt@canonical.com> * * The StarFive JH7110 requires to prepend a header to u-boot-spl.bin describing * the payload length and CRC32. * * This module implements support in mkimage and dumpimage for this file format. * * StarFive's spl_tool available under GPL-2.0-and-later at * https://github.com/starfive-tech/Tools implements writing the same file * format and served as a reference. */ #include <compiler.h> #include <fcntl.h> #include <u-boot/crc.h> #include <unistd.h> #include "imagetool.h" #define DEFAULT_VERSION 0x01010101 #define DEFAULT_BACKUP 0x200000U #define DEFAULT_OFFSET 0x240 /** * struct spl_hdr - header for SPL on JH7110 * * All fields are low-endian. */ struct spl_hdr { /** @offset: offset to SPL header (0x240) */ unsigned int offset; /** @bkp_offs: address of backup SPL, defaults to DEFAULT_BACKUP */ unsigned int bkp_offs; /** @zero1: set to zero */ unsigned int zero1[159]; /** @version: header version, defaults to DEFAULT_VERSION */ unsigned int version; /** @file_size: file size */ unsigned int file_size; /** @hdr_size: size of the file header (0x400) */ unsigned int hdr_size; /** @crc32: CRC32 */ unsigned int crc32; /** @zero2: set to zero */ unsigned int zero2[91]; }; static int sfspl_check_params(struct imgtool *itl) { /* Only the RISC-V architecture is supported */ if (itl->Aflag && itl->arch != IH_ARCH_RISCV) return EXIT_FAILURE; return EXIT_SUCCESS; } static int sfspl_verify_header(unsigned char *buf, int size, struct imgtool *itl) { struct spl_hdr *hdr = (void *)buf; unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); unsigned int file_size = le32_to_cpu(hdr->file_size); unsigned int crc = le32_to_cpu(hdr->crc32); unsigned int crc_check; if (size < 0 || (size_t)size < sizeof(struct spl_hdr) || (size_t)size < hdr_size + file_size) { printf("Truncated file\n"); return EXIT_FAILURE; } if ((size_t)size > hdr_size + file_size) printf("File too long, expected %u bytes\n", hdr_size + file_size); if (hdr->version != DEFAULT_VERSION) { printf("Unknown file format version\n"); return EXIT_FAILURE; } crc_check = crc32(0, &buf[hdr_size], file_size); if (crc_check != crc) { printf("Incorrect CRC32\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } static void sfspl_print_header(const void *buf, struct imgtool *itl) { struct spl_hdr *hdr = (void *)buf; unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); unsigned int file_size = le32_to_cpu(hdr->file_size); printf("Header size: %u\n", hdr_size); printf("Payload size: %u\n", file_size); } static int sfspl_image_extract_subimage(void *ptr, struct imgtool *itl) { struct spl_hdr *hdr = (void *)ptr; unsigned char *buf = ptr; int fd, ret = EXIT_SUCCESS; unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); unsigned int file_size = le32_to_cpu(hdr->file_size); if (itl->pflag) { printf("Invalid image index %d\n", itl->pflag); return EXIT_FAILURE; } fd = open(itl->outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { perror("Cannot open file"); return EXIT_FAILURE; } if (write(fd, &buf[hdr_size], file_size) != file_size) { perror("Cannot write file"); ret = EXIT_FAILURE; } close(fd); return ret; } static int sfspl_check_image_type(uint8_t type) { if (type == IH_TYPE_STARFIVE_SPL) return EXIT_SUCCESS; return EXIT_FAILURE; } static void sfspl_set_header(void *buf, struct stat *sbuf, int infd, struct imgtool *itl) { struct spl_hdr *hdr = buf; unsigned int file_size; unsigned int crc; file_size = itl->file_size - sizeof(struct spl_hdr); crc = crc32(0, &((unsigned char *)buf)[sizeof(struct spl_hdr)], file_size); hdr->offset = cpu_to_le32(DEFAULT_OFFSET); hdr->bkp_offs = cpu_to_le32(DEFAULT_BACKUP); hdr->version = cpu_to_le32(DEFAULT_VERSION); hdr->file_size = cpu_to_le32(file_size); hdr->hdr_size = cpu_to_le32(sizeof(struct spl_hdr)); hdr->crc32 = cpu_to_le32(crc); } static int sfspl_vrec_header(struct imgtool *itl, struct imgtool_funcs *tparams) { tparams->hdr = calloc(sizeof(struct spl_hdr), 1); /* No padding */ return 0; } U_BOOT_IMAGE_TYPE( sfspl, /* id */ "StarFive SPL Image", /* name */ sizeof(struct spl_hdr), /* header_size */ NULL, /* header */ sfspl_check_params, /* check_params */ sfspl_verify_header, /* verify header */ sfspl_print_header, /* print header */ sfspl_set_header, /* set header */ sfspl_image_extract_subimage, /* extract_subimage */ sfspl_check_image_type, /* check_image_type */ NULL, /* fflag_handle */ sfspl_vrec_header /* vrec_header */ ); |