Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[platform/kernel/u-boot.git] / tools / omapimage.c
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 "imagetool.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 image_tool_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 image_tool_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 image_tool_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         register_image_type(&omapimage_params);
251 }