1 /* 2 * (C) Copyright 2010 3 * Linaro LTD, www.linaro.org 4 * Author: John Rigby <john.rigby@linaro.org> 5 * Based on TI's signGP.c 6 * 7 * (C) Copyright 2009 8 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 9 * 10 * (C) Copyright 2008 11 * Marvell Semiconductor <www.marvell.com> 12 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 13 * 14 * SPDX-License-Identifier: GPL-2.0+ 15 */ 16 17 #include "mkimage.h" 18 #include <image.h> 19 #include "omapimage.h" 20 21 /* Header size is CH header rounded up to 512 bytes plus GP header */ 22 #define OMAP_CH_HDR_SIZE 512 23 #define OMAP_GP_HDR_SIZE (sizeof(struct gp_header)) 24 #define OMAP_FILE_HDR_SIZE (OMAP_CH_HDR_SIZE+OMAP_GP_HDR_SIZE) 25 26 static int do_swap32 = 0; 27 28 static uint32_t omapimage_swap32(uint32_t data) 29 { 30 uint32_t result = 0; 31 result = (data & 0xFF000000) >> 24; 32 result |= (data & 0x00FF0000) >> 8; 33 result |= (data & 0x0000FF00) << 8; 34 result |= (data & 0x000000FF) << 24; 35 return result; 36 } 37 38 static uint8_t omapimage_header[OMAP_FILE_HDR_SIZE]; 39 40 static int omapimage_check_image_types(uint8_t type) 41 { 42 if (type == IH_TYPE_OMAPIMAGE) 43 return EXIT_SUCCESS; 44 else { 45 return EXIT_FAILURE; 46 } 47 } 48 49 /* 50 * Only the simplest image type is currently supported: 51 * TOC pointing to CHSETTINGS 52 * TOC terminator 53 * CHSETTINGS 54 * 55 * padding to OMAP_CH_HDR_SIZE bytes 56 * 57 * gp header 58 * size 59 * load_addr 60 */ 61 static int valid_gph_size(uint32_t size) 62 { 63 return size; 64 } 65 66 static int valid_gph_load_addr(uint32_t load_addr) 67 { 68 return load_addr; 69 } 70 71 static int omapimage_verify_header(unsigned char *ptr, int image_size, 72 struct mkimage_params *params) 73 { 74 struct ch_toc *toc = (struct ch_toc *)ptr; 75 struct gp_header *gph = (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); 76 uint32_t offset, size, gph_size, gph_load_addr; 77 78 while (toc->section_offset != 0xffffffff 79 && toc->section_size != 0xffffffff) { 80 if (do_swap32) { 81 offset = omapimage_swap32(toc->section_offset); 82 size = omapimage_swap32(toc->section_size); 83 } else { 84 offset = toc->section_offset; 85 size = toc->section_size; 86 } 87 if (!offset || !size) 88 return -1; 89 if (offset >= OMAP_CH_HDR_SIZE || 90 offset+size >= OMAP_CH_HDR_SIZE) 91 return -1; 92 toc++; 93 } 94 95 if (do_swap32) { 96 gph_size = omapimage_swap32(gph->size); 97 gph_load_addr = omapimage_swap32(gph->load_addr); 98 } else { 99 gph_size = gph->size; 100 gph_load_addr = gph->load_addr; 101 } 102 103 if (!valid_gph_size(gph_size)) 104 return -1; 105 if (!valid_gph_load_addr(gph_load_addr)) 106 return -1; 107 108 return 0; 109 } 110 111 static void omapimage_print_section(struct ch_settings *chs) 112 { 113 const char *section_name; 114 115 if (chs->section_key) 116 section_name = "CHSETTINGS"; 117 else 118 section_name = "UNKNOWNKEY"; 119 120 printf("%s (%x) " 121 "valid:%x " 122 "version:%x " 123 "reserved:%x " 124 "flags:%x\n", 125 section_name, 126 chs->section_key, 127 chs->valid, 128 chs->version, 129 chs->reserved, 130 chs->flags); 131 } 132 133 static void omapimage_print_header(const void *ptr) 134 { 135 const struct ch_toc *toc = (struct ch_toc *)ptr; 136 const struct gp_header *gph = 137 (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); 138 uint32_t offset, size, gph_size, gph_load_addr; 139 140 while (toc->section_offset != 0xffffffff 141 && toc->section_size != 0xffffffff) { 142 if (do_swap32) { 143 offset = omapimage_swap32(toc->section_offset); 144 size = omapimage_swap32(toc->section_size); 145 } else { 146 offset = toc->section_offset; 147 size = toc->section_size; 148 } 149 150 if (offset >= OMAP_CH_HDR_SIZE || 151 offset+size >= OMAP_CH_HDR_SIZE) 152 exit(EXIT_FAILURE); 153 154 printf("Section %s offset %x length %x\n", 155 toc->section_name, 156 toc->section_offset, 157 toc->section_size); 158 159 omapimage_print_section((struct ch_settings *)(ptr+offset)); 160 toc++; 161 } 162 163 if (do_swap32) { 164 gph_size = omapimage_swap32(gph->size); 165 gph_load_addr = omapimage_swap32(gph->load_addr); 166 } else { 167 gph_size = gph->size; 168 gph_load_addr = gph->load_addr; 169 } 170 171 if (!valid_gph_size(gph_size)) { 172 fprintf(stderr, "Error: invalid image size %x\n", gph_size); 173 exit(EXIT_FAILURE); 174 } 175 176 if (!valid_gph_load_addr(gph_load_addr)) { 177 fprintf(stderr, "Error: invalid image load address %x\n", 178 gph_load_addr); 179 exit(EXIT_FAILURE); 180 } 181 182 printf("GP Header: Size %x LoadAddr %x\n", gph_size, gph_load_addr); 183 } 184 185 static int toc_offset(void *hdr, void *member) 186 { 187 return member - hdr; 188 } 189 190 static void omapimage_set_header(void *ptr, struct stat *sbuf, int ifd, 191 struct mkimage_params *params) 192 { 193 struct ch_toc *toc = (struct ch_toc *)ptr; 194 struct ch_settings *chs = (struct ch_settings *) 195 (ptr + 2 * sizeof(*toc)); 196 struct gp_header *gph = (struct gp_header *)(ptr + OMAP_CH_HDR_SIZE); 197 198 toc->section_offset = toc_offset(ptr, chs); 199 toc->section_size = sizeof(struct ch_settings); 200 strcpy((char *)toc->section_name, "CHSETTINGS"); 201 202 chs->section_key = KEY_CHSETTINGS; 203 chs->valid = 0; 204 chs->version = 1; 205 chs->reserved = 0; 206 chs->flags = 0; 207 208 toc++; 209 memset(toc, 0xff, sizeof(*toc)); 210 211 gph->size = sbuf->st_size - OMAP_FILE_HDR_SIZE; 212 gph->load_addr = params->addr; 213 214 if (strncmp(params->imagename, "byteswap", 8) == 0) { 215 do_swap32 = 1; 216 int swapped = 0; 217 uint32_t *data = (uint32_t *)ptr; 218 219 while (swapped <= (sbuf->st_size / sizeof(uint32_t))) { 220 *data = omapimage_swap32(*data); 221 swapped++; 222 data++; 223 } 224 } 225 } 226 227 int omapimage_check_params(struct mkimage_params *params) 228 { 229 return (params->dflag && (params->fflag || params->lflag)) || 230 (params->fflag && (params->dflag || params->lflag)) || 231 (params->lflag && (params->dflag || params->fflag)); 232 } 233 234 /* 235 * omapimage parameters 236 */ 237 static struct image_type_params omapimage_params = { 238 .name = "TI OMAP CH/GP Boot Image support", 239 .header_size = OMAP_FILE_HDR_SIZE, 240 .hdr = (void *)&omapimage_header, 241 .check_image_type = omapimage_check_image_types, 242 .verify_header = omapimage_verify_header, 243 .print_header = omapimage_print_header, 244 .set_header = omapimage_set_header, 245 .check_params = omapimage_check_params, 246 }; 247 248 void init_omap_image_type(void) 249 { 250 mkimage_register(&omapimage_params); 251 } 252