xref: /openbmc/u-boot/tools/omapimage.c (revision 03efcb05)
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