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 * See file CREDITS for list of people who contributed to this 15 * project. 16 * 17 * This program is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU General Public License as 19 * published by the Free Software Foundation; either version 2 of 20 * the License, or (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 30 * MA 02111-1307 USA 31 */ 32 33 /* Required to obtain the getline prototype from stdio.h */ 34 #define _GNU_SOURCE 35 36 #include "mkimage.h" 37 #include <image.h> 38 #include "omapimage.h" 39 40 /* Header size is CH header rounded up to 512 bytes plus GP header */ 41 #define OMAP_CH_HDR_SIZE 512 42 #define OMAP_GP_HDR_SIZE (sizeof(struct gp_header)) 43 #define OMAP_FILE_HDR_SIZE (OMAP_CH_HDR_SIZE+OMAP_GP_HDR_SIZE) 44 45 static int do_swap32 = 0; 46 47 static uint32_t omapimage_swap32(uint32_t data) 48 { 49 uint32_t result = 0; 50 result = (data & 0xFF000000) >> 24; 51 result |= (data & 0x00FF0000) >> 8; 52 result |= (data & 0x0000FF00) << 8; 53 result |= (data & 0x000000FF) << 24; 54 return result; 55 } 56 57 static uint8_t omapimage_header[OMAP_FILE_HDR_SIZE]; 58 59 static int omapimage_check_image_types(uint8_t type) 60 { 61 if (type == IH_TYPE_OMAPIMAGE) 62 return EXIT_SUCCESS; 63 else { 64 return EXIT_FAILURE; 65 } 66 } 67 68 /* 69 * Only the simplest image type is currently supported: 70 * TOC pointing to CHSETTINGS 71 * TOC terminator 72 * CHSETTINGS 73 * 74 * padding to OMAP_CH_HDR_SIZE bytes 75 * 76 * gp header 77 * size 78 * load_addr 79 */ 80 static int valid_gph_size(uint32_t size) 81 { 82 return size; 83 } 84 85 static int valid_gph_load_addr(uint32_t load_addr) 86 { 87 return load_addr; 88 } 89 90 static int omapimage_verify_header(unsigned char *ptr, int image_size, 91 struct mkimage_params *params) 92 { 93 struct ch_toc *toc = (struct ch_toc *)ptr; 94 struct gp_header *gph = (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); 95 uint32_t offset, size, gph_size, gph_load_addr; 96 97 while (toc->section_offset != 0xffffffff 98 && toc->section_size != 0xffffffff) { 99 if (do_swap32) { 100 offset = omapimage_swap32(toc->section_offset); 101 size = omapimage_swap32(toc->section_size); 102 } else { 103 offset = toc->section_offset; 104 size = toc->section_size; 105 } 106 if (!offset || !size) 107 return -1; 108 if (offset >= OMAP_CH_HDR_SIZE || 109 offset+size >= OMAP_CH_HDR_SIZE) 110 return -1; 111 toc++; 112 } 113 114 if (do_swap32) { 115 gph_size = omapimage_swap32(gph->size); 116 gph_load_addr = omapimage_swap32(gph->load_addr); 117 } else { 118 gph_size = gph->size; 119 gph_load_addr = gph->load_addr; 120 } 121 122 if (!valid_gph_size(gph_size)) 123 return -1; 124 if (!valid_gph_load_addr(gph_load_addr)) 125 return -1; 126 127 return 0; 128 } 129 130 static void omapimage_print_section(struct ch_settings *chs) 131 { 132 const char *section_name; 133 134 if (chs->section_key) 135 section_name = "CHSETTINGS"; 136 else 137 section_name = "UNKNOWNKEY"; 138 139 printf("%s (%x) " 140 "valid:%x " 141 "version:%x " 142 "reserved:%x " 143 "flags:%x\n", 144 section_name, 145 chs->section_key, 146 chs->valid, 147 chs->version, 148 chs->reserved, 149 chs->flags); 150 } 151 152 static void omapimage_print_header(const void *ptr) 153 { 154 const struct ch_toc *toc = (struct ch_toc *)ptr; 155 const struct gp_header *gph = 156 (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); 157 uint32_t offset, size, gph_size, gph_load_addr; 158 159 while (toc->section_offset != 0xffffffff 160 && toc->section_size != 0xffffffff) { 161 if (do_swap32) { 162 offset = omapimage_swap32(toc->section_offset); 163 size = omapimage_swap32(toc->section_size); 164 } else { 165 offset = toc->section_offset; 166 size = toc->section_size; 167 } 168 169 if (offset >= OMAP_CH_HDR_SIZE || 170 offset+size >= OMAP_CH_HDR_SIZE) 171 exit(EXIT_FAILURE); 172 173 printf("Section %s offset %x length %x\n", 174 toc->section_name, 175 toc->section_offset, 176 toc->section_size); 177 178 omapimage_print_section((struct ch_settings *)(ptr+offset)); 179 toc++; 180 } 181 182 if (do_swap32) { 183 gph_size = omapimage_swap32(gph->size); 184 gph_load_addr = omapimage_swap32(gph->load_addr); 185 } else { 186 gph_size = gph->size; 187 gph_load_addr = gph->load_addr; 188 } 189 190 if (!valid_gph_size(gph_size)) { 191 fprintf(stderr, "Error: invalid image size %x\n", gph_size); 192 exit(EXIT_FAILURE); 193 } 194 195 if (!valid_gph_load_addr(gph_load_addr)) { 196 fprintf(stderr, "Error: invalid image load address %x\n", 197 gph_load_addr); 198 exit(EXIT_FAILURE); 199 } 200 201 printf("GP Header: Size %x LoadAddr %x\n", gph_size, gph_load_addr); 202 } 203 204 static int toc_offset(void *hdr, void *member) 205 { 206 return member - hdr; 207 } 208 209 static void omapimage_set_header(void *ptr, struct stat *sbuf, int ifd, 210 struct mkimage_params *params) 211 { 212 struct ch_toc *toc = (struct ch_toc *)ptr; 213 struct ch_settings *chs = (struct ch_settings *) 214 (ptr + 2 * sizeof(*toc)); 215 struct gp_header *gph = (struct gp_header *)(ptr + OMAP_CH_HDR_SIZE); 216 217 toc->section_offset = toc_offset(ptr, chs); 218 toc->section_size = sizeof(struct ch_settings); 219 strcpy((char *)toc->section_name, "CHSETTINGS"); 220 221 chs->section_key = KEY_CHSETTINGS; 222 chs->valid = 0; 223 chs->version = 1; 224 chs->reserved = 0; 225 chs->flags = 0; 226 227 toc++; 228 memset(toc, 0xff, sizeof(*toc)); 229 230 gph->size = sbuf->st_size - OMAP_FILE_HDR_SIZE; 231 gph->load_addr = params->addr; 232 233 if (strncmp(params->imagename, "byteswap", 8) == 0) { 234 do_swap32 = 1; 235 int swapped = 0; 236 uint32_t *data = (uint32_t *)ptr; 237 238 while (swapped <= (sbuf->st_size / sizeof(uint32_t))) { 239 *data = omapimage_swap32(*data); 240 swapped++; 241 data++; 242 } 243 } 244 } 245 246 int omapimage_check_params(struct mkimage_params *params) 247 { 248 return (params->dflag && (params->fflag || params->lflag)) || 249 (params->fflag && (params->dflag || params->lflag)) || 250 (params->lflag && (params->dflag || params->fflag)); 251 } 252 253 /* 254 * omapimage parameters 255 */ 256 static struct image_type_params omapimage_params = { 257 .name = "TI OMAP CH/GP Boot Image support", 258 .header_size = OMAP_FILE_HDR_SIZE, 259 .hdr = (void *)&omapimage_header, 260 .check_image_type = omapimage_check_image_types, 261 .verify_header = omapimage_verify_header, 262 .print_header = omapimage_print_header, 263 .set_header = omapimage_set_header, 264 .check_params = omapimage_check_params, 265 }; 266 267 void init_omap_image_type(void) 268 { 269 mkimage_register(&omapimage_params); 270 } 271