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