]> git.sur5r.net Git - u-boot/blob - tools/rkcommon.c
rockchip: mkimage: play nice with dumpimage
[u-boot] / tools / rkcommon.c
1 /*
2  * (C) Copyright 2015 Google,  Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  *
7  * Helper functions for Rockchip images
8  */
9
10 #include "imagetool.h"
11 #include <image.h>
12 #include <rc4.h>
13 #include "mkimage.h"
14 #include "rkcommon.h"
15
16 #define DIV_ROUND_UP(n, d)      (((n) + (d) - 1) / (d))
17
18 enum {
19         RK_SIGNATURE            = 0x0ff0aa55,
20 };
21
22 /**
23  * struct header0_info - header block for boot ROM
24  *
25  * This is stored at SD card block 64 (where each block is 512 bytes, or at
26  * the start of SPI flash. It is encoded with RC4.
27  *
28  * @signature:          Signature (must be RKSD_SIGNATURE)
29  * @disable_rc4:        0 to use rc4 for boot image,  1 to use plain binary
30  * @init_offset:        Offset in blocks of the SPL code from this header
31  *                      block. E.g. 4 means 2KB after the start of this header.
32  * Other fields are not used by U-Boot
33  */
34 struct header0_info {
35         uint32_t signature;
36         uint8_t reserved[4];
37         uint32_t disable_rc4;
38         uint16_t init_offset;
39         uint8_t reserved1[492];
40         uint16_t init_size;
41         uint16_t init_boot_size;
42         uint8_t reserved2[2];
43 };
44
45 /**
46  * struct header1_info
47  */
48 struct header1_info {
49         uint32_t magic;
50 };
51
52 /**
53  * struct spl_info - spl info for each chip
54  *
55  * @imagename:          Image name(passed by "mkimage -n")
56  * @spl_hdr:            Boot ROM requires a 4-bytes spl header
57  * @spl_size:           Spl size(include extra 4-bytes spl header)
58  * @spl_rc4:            RC4 encode the SPL binary (same key as header)
59  * @spl_boot0:          A new-style (ARM_SOC_BOOT0_HOOK) image that should
60  *                      have the boot magic (e.g. 'RK33') written to its first
61  *                      word.
62  */
63
64 struct spl_info {
65         const char *imagename;
66         const char *spl_hdr;
67         const uint32_t spl_size;
68         const bool spl_rc4;
69         const bool spl_boot0;
70 };
71
72 static struct spl_info spl_infos[] = {
73         { "rk3036", "RK30", 0x1000, false, false },
74         { "rk3188", "RK31", 0x8000 - 0x800, true, false },
75         { "rk3288", "RK32", 0x8000, false, false },
76         { "rk3328", "RK32", 0x8000 - 0x1000, false, false },
77         { "rk3399", "RK33", 0x20000, false, true },
78 };
79
80 static unsigned char rc4_key[16] = {
81         124, 78, 3, 4, 85, 5, 9, 7,
82         45, 44, 123, 56, 23, 13, 23, 17
83 };
84
85 static struct spl_info *rkcommon_get_spl_info(char *imagename)
86 {
87         int i;
88
89         if (!imagename)
90                 return NULL;
91
92         for (i = 0; i < ARRAY_SIZE(spl_infos); i++)
93                 if (!strncmp(imagename, spl_infos[i].imagename, 6))
94                         return spl_infos + i;
95
96         return NULL;
97 }
98
99 int rkcommon_check_params(struct image_tool_params *params)
100 {
101         int i;
102
103         if (rkcommon_get_spl_info(params->imagename) != NULL)
104                 return EXIT_SUCCESS;
105
106         /*
107          * If this is a operation (list or extract), the don't require
108          * imagename to be set.
109          */
110         if (params->lflag || params->iflag)
111                 return EXIT_SUCCESS;
112
113         fprintf(stderr, "ERROR: imagename (%s) is not supported!\n",
114                 params->imagename ? params->imagename : "NULL");
115
116         fprintf(stderr, "Available imagename:");
117         for (i = 0; i < ARRAY_SIZE(spl_infos); i++)
118                 fprintf(stderr, "\t%s", spl_infos[i].imagename);
119         fprintf(stderr, "\n");
120
121         return EXIT_FAILURE;
122 }
123
124 const char *rkcommon_get_spl_hdr(struct image_tool_params *params)
125 {
126         struct spl_info *info = rkcommon_get_spl_info(params->imagename);
127
128         /*
129          * info would not be NULL, because of we checked params before.
130          */
131         return info->spl_hdr;
132 }
133
134
135 int rkcommon_get_spl_size(struct image_tool_params *params)
136 {
137         struct spl_info *info = rkcommon_get_spl_info(params->imagename);
138
139         /*
140          * info would not be NULL, because of we checked params before.
141          */
142         return info->spl_size;
143 }
144
145 bool rkcommon_need_rc4_spl(struct image_tool_params *params)
146 {
147         struct spl_info *info = rkcommon_get_spl_info(params->imagename);
148
149         /*
150          * info would not be NULL, because of we checked params before.
151          */
152         return info->spl_rc4;
153 }
154
155 bool rkcommon_spl_is_boot0(struct image_tool_params *params)
156 {
157         struct spl_info *info = rkcommon_get_spl_info(params->imagename);
158
159         /*
160          * info would not be NULL, because of we checked params before.
161          */
162         return info->spl_boot0;
163 }
164
165 static void rkcommon_set_header0(void *buf, uint file_size,
166                                  struct image_tool_params *params)
167 {
168         struct header0_info *hdr = buf;
169
170         memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
171         hdr->signature = RK_SIGNATURE;
172         hdr->disable_rc4 = !rkcommon_need_rc4_spl(params);
173         hdr->init_offset = RK_INIT_OFFSET;
174
175         hdr->init_size = DIV_ROUND_UP(file_size, RK_BLK_SIZE);
176         /*
177          * The init_size has to be a multiple of 4 blocks (i.e. of 2K)
178          * or the BootROM will not boot the image.
179          *
180          * Note: To verify that this is not a legacy constraint, we
181          *       rechecked this against the RK3399 BootROM.
182          */
183         hdr->init_size = ROUND(hdr->init_size, 4);
184         /*
185          * The images we create do not contain the stage following the SPL as
186          * part of the SPL image, so the init_boot_size (which might have been
187          * read by Rockchip's miniloder) should be the same as the init_size.
188          */
189         hdr->init_boot_size = hdr->init_size;
190
191         rc4_encode(buf, RK_BLK_SIZE, rc4_key);
192 }
193
194 int rkcommon_set_header(void *buf, uint file_size,
195                         struct image_tool_params *params)
196 {
197         struct header1_info *hdr = buf + RK_SPL_HDR_START;
198
199         if (file_size > rkcommon_get_spl_size(params))
200                 return -ENOSPC;
201
202         rkcommon_set_header0(buf, file_size, params);
203
204         /* Set up the SPL name */
205         memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
206
207         if (rkcommon_need_rc4_spl(params))
208                 rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START,
209                                         params->file_size - RK_SPL_HDR_START);
210
211         return 0;
212 }
213
214 void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size)
215 {
216         unsigned int remaining = size;
217
218         while (remaining > 0) {
219                 int step = (remaining > RK_BLK_SIZE) ? RK_BLK_SIZE : remaining;
220
221                 rc4_encode(buf + offset, step, rc4_key);
222                 offset += RK_BLK_SIZE;
223                 remaining -= step;
224         }
225 }
226
227 int rkcommon_vrec_header(struct image_tool_params *params,
228                          struct image_type_params *tparams,
229                          unsigned int alignment)
230 {
231         unsigned int  unpadded_size;
232         unsigned int  padded_size;
233
234         /*
235          * The SPL image looks as follows:
236          *
237          * 0x0    header0 (see rkcommon.c)
238          * 0x800  spl_name ('RK30', ..., 'RK33')
239          *        (start of the payload for AArch64 payloads: we expect the
240          *        first 4 bytes to be available for overwriting with our
241          *        spl_name)
242          * 0x804  first instruction to be executed
243          *        (start of the image/payload for 32bit payloads)
244          *
245          * For AArch64 (ARMv8) payloads, natural alignment (8-bytes) is
246          * required for its sections (so the image we receive needs to
247          * have the first 4 bytes reserved for the spl_name).  Reserving
248          * these 4 bytes is done using the BOOT0_HOOK infrastructure.
249          *
250          * Depending on this, the header is either 0x800 (if this is a
251          * 'boot0'-style payload, which has reserved 4 bytes at the
252          * beginning for the 'spl_name' and expects us to overwrite
253          * its first 4 bytes) or 0x804 bytes in length.
254          */
255         if (rkcommon_spl_is_boot0(params))
256                 tparams->header_size = RK_SPL_HDR_START;
257         else
258                 tparams->header_size = RK_SPL_HDR_START + 4;
259
260         /* Allocate, clear and install the header */
261         tparams->hdr = malloc(tparams->header_size);
262         memset(tparams->hdr, 0, tparams->header_size);
263         tparams->header_size = tparams->header_size;
264
265         /*
266          * If someone passed in 0 for the alignment, we'd better handle
267          * it correctly...
268          */
269         if (!alignment)
270                 alignment = 1;
271
272         unpadded_size = tparams->header_size + params->file_size;
273         padded_size = ROUND(unpadded_size, alignment);
274
275         return padded_size - unpadded_size;
276 }