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