1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Freescale i.MX28 SB image generator
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2012 Marek Vasut <marex@denx.de>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #ifndef __MXSSB_H__
10*4882a593Smuzhiyun #define __MXSSB_H__
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <stdint.h>
13*4882a593Smuzhiyun #include <arpa/inet.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define SB_BLOCK_SIZE 16
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
18*4882a593Smuzhiyun #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun struct sb_boot_image_version {
21*4882a593Smuzhiyun uint16_t major;
22*4882a593Smuzhiyun uint16_t pad0;
23*4882a593Smuzhiyun uint16_t minor;
24*4882a593Smuzhiyun uint16_t pad1;
25*4882a593Smuzhiyun uint16_t revision;
26*4882a593Smuzhiyun uint16_t pad2;
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun struct sb_boot_image_header {
30*4882a593Smuzhiyun union {
31*4882a593Smuzhiyun /* SHA1 of the header. */
32*4882a593Smuzhiyun uint8_t digest[20];
33*4882a593Smuzhiyun struct {
34*4882a593Smuzhiyun /* CBC-MAC initialization vector. */
35*4882a593Smuzhiyun uint8_t iv[16];
36*4882a593Smuzhiyun uint8_t extra[4];
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun /* 'STMP' */
40*4882a593Smuzhiyun uint8_t signature1[4];
41*4882a593Smuzhiyun /* Major version of the image format. */
42*4882a593Smuzhiyun uint8_t major_version;
43*4882a593Smuzhiyun /* Minor version of the image format. */
44*4882a593Smuzhiyun uint8_t minor_version;
45*4882a593Smuzhiyun /* Flags associated with the image. */
46*4882a593Smuzhiyun uint16_t flags;
47*4882a593Smuzhiyun /* Size of the image in 16b blocks. */
48*4882a593Smuzhiyun uint32_t image_blocks;
49*4882a593Smuzhiyun /* Offset of the first tag in 16b blocks. */
50*4882a593Smuzhiyun uint32_t first_boot_tag_block;
51*4882a593Smuzhiyun /* ID of the section to boot from. */
52*4882a593Smuzhiyun uint32_t first_boot_section_id;
53*4882a593Smuzhiyun /* Amount of crypto keys. */
54*4882a593Smuzhiyun uint16_t key_count;
55*4882a593Smuzhiyun /* Offset to the key dictionary in 16b blocks. */
56*4882a593Smuzhiyun uint16_t key_dictionary_block;
57*4882a593Smuzhiyun /* Size of this header in 16b blocks. */
58*4882a593Smuzhiyun uint16_t header_blocks;
59*4882a593Smuzhiyun /* Amount of section headers. */
60*4882a593Smuzhiyun uint16_t section_count;
61*4882a593Smuzhiyun /* Section header size in 16b blocks. */
62*4882a593Smuzhiyun uint16_t section_header_size;
63*4882a593Smuzhiyun /* Padding to align timestamp to uint64_t. */
64*4882a593Smuzhiyun uint8_t padding0[2];
65*4882a593Smuzhiyun /* 'sgtl' (since v1.1) */
66*4882a593Smuzhiyun uint8_t signature2[4];
67*4882a593Smuzhiyun /* Image generation date, in microseconds since 1.1.2000 . */
68*4882a593Smuzhiyun uint64_t timestamp_us;
69*4882a593Smuzhiyun /* Product version. */
70*4882a593Smuzhiyun struct sb_boot_image_version
71*4882a593Smuzhiyun product_version;
72*4882a593Smuzhiyun /* Component version. */
73*4882a593Smuzhiyun struct sb_boot_image_version
74*4882a593Smuzhiyun component_version;
75*4882a593Smuzhiyun /* Drive tag for the system drive. (since v1.1) */
76*4882a593Smuzhiyun uint16_t drive_tag;
77*4882a593Smuzhiyun /* Padding. */
78*4882a593Smuzhiyun uint8_t padding1[6];
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun #define SB_VERSION_MAJOR 1
82*4882a593Smuzhiyun #define SB_VERSION_MINOR 1
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /* Enable to HTLLC boot report. */
85*4882a593Smuzhiyun #define SB_IMAGE_FLAG_DISPLAY_PROGRESS (1 << 0)
86*4882a593Smuzhiyun #define SB_IMAGE_FLAGS_MASK SB_IMAGE_FLAG_DISPLAY_PROGRESS
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun struct sb_key_dictionary_key {
89*4882a593Smuzhiyun /* The CBC-MAC of image and sections header. */
90*4882a593Smuzhiyun uint8_t cbc_mac[SB_BLOCK_SIZE];
91*4882a593Smuzhiyun /* The AES key encrypted by image key (zero). */
92*4882a593Smuzhiyun uint8_t key[SB_BLOCK_SIZE];
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun struct sb_ivt_header {
96*4882a593Smuzhiyun uint32_t header;
97*4882a593Smuzhiyun uint32_t entry;
98*4882a593Smuzhiyun uint32_t reserved1;
99*4882a593Smuzhiyun uint32_t dcd;
100*4882a593Smuzhiyun uint32_t boot_data;
101*4882a593Smuzhiyun uint32_t self;
102*4882a593Smuzhiyun uint32_t csf;
103*4882a593Smuzhiyun uint32_t reserved2;
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun #define SB_HAB_IVT_TAG 0xd1UL
107*4882a593Smuzhiyun #define SB_HAB_DCD_TAG 0xd2UL
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun #define SB_HAB_VERSION 0x40UL
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun * The "size" field in the IVT header is not naturally aligned,
113*4882a593Smuzhiyun * use this macro to fill first 4 bytes of the IVT header without
114*4882a593Smuzhiyun * causing issues on some systems (esp. M68k, PPC, MIPS-BE, ARM-BE).
115*4882a593Smuzhiyun */
sb_hab_ivt_header(void)116*4882a593Smuzhiyun static inline uint32_t sb_hab_ivt_header(void)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun uint32_t ret = 0;
119*4882a593Smuzhiyun ret |= SB_HAB_IVT_TAG << 24;
120*4882a593Smuzhiyun ret |= sizeof(struct sb_ivt_header) << 16;
121*4882a593Smuzhiyun ret |= SB_HAB_VERSION;
122*4882a593Smuzhiyun return htonl(ret);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun struct sb_sections_header {
126*4882a593Smuzhiyun /* Section number. */
127*4882a593Smuzhiyun uint32_t section_number;
128*4882a593Smuzhiyun /* Offset of this sections first instruction after "TAG". */
129*4882a593Smuzhiyun uint32_t section_offset;
130*4882a593Smuzhiyun /* Size of the section in 16b blocks. */
131*4882a593Smuzhiyun uint32_t section_size;
132*4882a593Smuzhiyun /* Section flags. */
133*4882a593Smuzhiyun uint32_t section_flags;
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun #define SB_SECTION_FLAG_BOOTABLE (1 << 0)
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun struct sb_command {
139*4882a593Smuzhiyun struct {
140*4882a593Smuzhiyun uint8_t checksum;
141*4882a593Smuzhiyun uint8_t tag;
142*4882a593Smuzhiyun uint16_t flags;
143*4882a593Smuzhiyun #define ROM_TAG_CMD_FLAG_ROM_LAST_TAG 0x1
144*4882a593Smuzhiyun #define ROM_LOAD_CMD_FLAG_DCD_LOAD 0x1 /* MX28 only */
145*4882a593Smuzhiyun #define ROM_JUMP_CMD_FLAG_HAB 0x1 /* MX28 only */
146*4882a593Smuzhiyun #define ROM_CALL_CMD_FLAG_HAB 0x1 /* MX28 only */
147*4882a593Smuzhiyun } header;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun union {
150*4882a593Smuzhiyun struct {
151*4882a593Smuzhiyun uint32_t reserved[3];
152*4882a593Smuzhiyun } nop;
153*4882a593Smuzhiyun struct {
154*4882a593Smuzhiyun uint32_t section_number;
155*4882a593Smuzhiyun uint32_t section_length;
156*4882a593Smuzhiyun uint32_t section_flags;
157*4882a593Smuzhiyun } tag;
158*4882a593Smuzhiyun struct {
159*4882a593Smuzhiyun uint32_t address;
160*4882a593Smuzhiyun uint32_t count;
161*4882a593Smuzhiyun uint32_t crc32;
162*4882a593Smuzhiyun } load;
163*4882a593Smuzhiyun struct {
164*4882a593Smuzhiyun uint32_t address;
165*4882a593Smuzhiyun uint32_t count;
166*4882a593Smuzhiyun uint32_t pattern;
167*4882a593Smuzhiyun } fill;
168*4882a593Smuzhiyun struct {
169*4882a593Smuzhiyun uint32_t address;
170*4882a593Smuzhiyun uint32_t reserved;
171*4882a593Smuzhiyun /* Passed in register r0 before JUMP */
172*4882a593Smuzhiyun uint32_t argument;
173*4882a593Smuzhiyun } jump;
174*4882a593Smuzhiyun struct {
175*4882a593Smuzhiyun uint32_t address;
176*4882a593Smuzhiyun uint32_t reserved;
177*4882a593Smuzhiyun /* Passed in register r0 before CALL */
178*4882a593Smuzhiyun uint32_t argument;
179*4882a593Smuzhiyun } call;
180*4882a593Smuzhiyun struct {
181*4882a593Smuzhiyun uint32_t reserved1;
182*4882a593Smuzhiyun uint32_t reserved2;
183*4882a593Smuzhiyun uint32_t mode;
184*4882a593Smuzhiyun } mode;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /*
190*4882a593Smuzhiyun * Most of the mode names are same or at least similar
191*4882a593Smuzhiyun * on i.MX23 and i.MX28, but some of the mode names
192*4882a593Smuzhiyun * differ. The "name" field represents the mode name
193*4882a593Smuzhiyun * on i.MX28 as seen in Table 12-2 of the datasheet.
194*4882a593Smuzhiyun * The "altname" field represents the differently named
195*4882a593Smuzhiyun * fields on i.MX23 as seen in Table 35-3 of the
196*4882a593Smuzhiyun * datasheet.
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun static const struct {
199*4882a593Smuzhiyun const char *name;
200*4882a593Smuzhiyun const char *altname;
201*4882a593Smuzhiyun const uint8_t mode;
202*4882a593Smuzhiyun } modetable[] = {
203*4882a593Smuzhiyun { "USB", NULL, 0x00 },
204*4882a593Smuzhiyun { "I2C", NULL, 0x01 },
205*4882a593Smuzhiyun { "SPI2_FLASH", "SPI1_FLASH", 0x02 },
206*4882a593Smuzhiyun { "SPI3_FLASH", "SPI2_FLASH", 0x03 },
207*4882a593Smuzhiyun { "NAND_BCH", NULL, 0x04 },
208*4882a593Smuzhiyun { "JTAG", NULL, 0x06 },
209*4882a593Smuzhiyun { "SPI3_EEPROM", "SPI2_EEPROM", 0x08 },
210*4882a593Smuzhiyun { "SD_SSP0", NULL, 0x09 },
211*4882a593Smuzhiyun { "SD_SSP1", NULL, 0x0A }
212*4882a593Smuzhiyun };
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun enum sb_tag {
215*4882a593Smuzhiyun ROM_NOP_CMD = 0x00,
216*4882a593Smuzhiyun ROM_TAG_CMD = 0x01,
217*4882a593Smuzhiyun ROM_LOAD_CMD = 0x02,
218*4882a593Smuzhiyun ROM_FILL_CMD = 0x03,
219*4882a593Smuzhiyun ROM_JUMP_CMD = 0x04,
220*4882a593Smuzhiyun ROM_CALL_CMD = 0x05,
221*4882a593Smuzhiyun ROM_MODE_CMD = 0x06
222*4882a593Smuzhiyun };
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun struct sb_source_entry {
225*4882a593Smuzhiyun uint8_t tag;
226*4882a593Smuzhiyun uint32_t address;
227*4882a593Smuzhiyun uint32_t flags;
228*4882a593Smuzhiyun char *filename;
229*4882a593Smuzhiyun };
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun #endif /* __MXSSB_H__ */
232