blob: d4d77d8858ea9d609590a0cf8c1a566eb5b0b328 [file] [log] [blame]
John Rigby3decb142011-07-21 09:10:30 -04001/*
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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020014 * SPDX-License-Identifier: GPL-2.0+
John Rigby3decb142011-07-21 09:10:30 -040015 */
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
Tom Rini79b9ebb2012-10-16 13:06:06 +000029static int do_swap32 = 0;
30
31static 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
John Rigby3decb142011-07-21 09:10:30 -040041static uint8_t omapimage_header[OMAP_FILE_HDR_SIZE];
42
43static int omapimage_check_image_types(uint8_t type)
44{
45 if (type == IH_TYPE_OMAPIMAGE)
46 return EXIT_SUCCESS;
47 else {
John Rigby3decb142011-07-21 09:10:30 -040048 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 */
64static int valid_gph_size(uint32_t size)
65{
66 return size;
67}
68
69static int valid_gph_load_addr(uint32_t load_addr)
70{
71 return load_addr;
72}
73
74static 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);
Tom Rini79b9ebb2012-10-16 13:06:06 +000079 uint32_t offset, size, gph_size, gph_load_addr;
John Rigby3decb142011-07-21 09:10:30 -040080
81 while (toc->section_offset != 0xffffffff
82 && toc->section_size != 0xffffffff) {
Tom Rini79b9ebb2012-10-16 13:06:06 +000083 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 }
John Rigby3decb142011-07-21 09:10:30 -040090 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 }
Tom Rini79b9ebb2012-10-16 13:06:06 +000097
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))
John Rigby3decb142011-07-21 09:10:30 -0400107 return -1;
Tom Rini79b9ebb2012-10-16 13:06:06 +0000108 if (!valid_gph_load_addr(gph_load_addr))
John Rigby3decb142011-07-21 09:10:30 -0400109 return -1;
110
111 return 0;
112}
113
114static 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
136static 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);
Tom Rini79b9ebb2012-10-16 13:06:06 +0000141 uint32_t offset, size, gph_size, gph_load_addr;
John Rigby3decb142011-07-21 09:10:30 -0400142
143 while (toc->section_offset != 0xffffffff
144 && toc->section_size != 0xffffffff) {
Tom Rini79b9ebb2012-10-16 13:06:06 +0000145 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 }
John Rigby3decb142011-07-21 09:10:30 -0400152
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
Tom Rini79b9ebb2012-10-16 13:06:06 +0000166 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);
John Rigby3decb142011-07-21 09:10:30 -0400176 exit(EXIT_FAILURE);
177 }
178
Tom Rini79b9ebb2012-10-16 13:06:06 +0000179 if (!valid_gph_load_addr(gph_load_addr)) {
180 fprintf(stderr, "Error: invalid image load address %x\n",
181 gph_load_addr);
John Rigby3decb142011-07-21 09:10:30 -0400182 exit(EXIT_FAILURE);
183 }
184
Tom Rini79b9ebb2012-10-16 13:06:06 +0000185 printf("GP Header: Size %x LoadAddr %x\n", gph_size, gph_load_addr);
John Rigby3decb142011-07-21 09:10:30 -0400186}
187
188static int toc_offset(void *hdr, void *member)
189{
190 return member - hdr;
191}
192
193static 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;
Tom Rini79b9ebb2012-10-16 13:06:06 +0000216
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 }
John Rigby3decb142011-07-21 09:10:30 -0400228}
229
230int 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 */
240static 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
251void init_omap_image_type(void)
252{
253 mkimage_register(&omapimage_params);
254}