forked from linux-sunxi/sunxi-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootinfo.c
384 lines (351 loc) · 12.4 KB
/
bootinfo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
/*
* (C) Copyright 2012 Henrik Nordstrom <[email protected]>
*
* display information about sunxi boot headers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "common.h"
#include "types.h"
/* boot_file_head copied from mksunxiboot */
/* boot head definition from sun4i boot code */
typedef struct boot_file_head
{
u32 jump_instruction; // one intruction jumping to real code
u8 magic[8]; // ="eGON.BT0" or "eGON.BT1", not C-style string.
u32 check_sum; // generated by PC
u32 length; // generated by PC
u32 pub_head_size; // the size of boot_file_head_t
u8 pub_head_vsn[4]; // the version of boot_file_head_t
u8 file_head_vsn[4]; // the version of boot0_file_head_t or boot1_file_head_t
u8 Boot_vsn[4]; // Boot version
u8 eGON_vsn[4]; // eGON version
u8 platform[8]; // platform information
} boot_file_head_t;
typedef struct brom_file_head
{
u32 jump_instruction; // one intruction jumping to real code
u8 magic[8]; // ="eGON.BRM", not C-style string.
u32 length; // generated by PC
u8 Boot_vsn[4]; // Boot version
u8 eGON_vsn[4]; // eGON version
u8 platform[8]; // platform information
} brom_file_head_t;
typedef struct _boot_dram_para_t {
__u32 dram_baseaddr;
__u32 dram_clk;
__u32 dram_type;
__u32 dram_rank_num;
__u32 dram_chip_density;
__u32 dram_io_width;
__u32 dram_bus_width;
__u32 dram_cas;
__u32 dram_zq;
__u32 dram_odt_en;
__u32 dram_size;
__u32 dram_tpr0;
__u32 dram_tpr1;
__u32 dram_tpr2;
__u32 dram_tpr3;
__u32 dram_tpr4;
__u32 dram_tpr5;
__u32 dram_emr1;
__u32 dram_emr2;
__u32 dram_emr3;
} boot_dram_para_t;
typedef struct _normal_gpio_cfg {
__u8 port;
__u8 port_num;
__u8 mul_sel;
__u8 pull;
__u8 drv_level;
__u8 data;
__u8 reserved[2];
} normal_gpio_cfg;
typedef struct _boot0_private_head_t {
__u32 prvt_head_size;
char prvt_head_vsn[4];
boot_dram_para_t dram_para;
__s32 uart_port;
normal_gpio_cfg uart_ctrl[2];
__s32 enable_jtag;
normal_gpio_cfg jtag_gpio[5];
normal_gpio_cfg storage_gpio[32];
__u8 storage_data[256];
} boot0_private_head_t;
typedef struct _boot0_file_head_t {
boot_file_head_t boot_head;
boot0_private_head_t prvt_head;
} boot0_file_head_t;
typedef struct _boot_core_para_t {
__u32 user_set_clock;
__u32 user_set_core_vol;
__u32 vol_threshold;
} boot_core_para_t;
typedef struct _boot1_private_head_t {
__u32 prvt_head_size;
__u8 prvt_head_vsn[4];
__s32 uart_port;
normal_gpio_cfg uart_ctrl[2];
boot_dram_para_t dram_para;
char script_buf[32768];
boot_core_para_t core_para;
__s32 twi_port;
normal_gpio_cfg twi_ctrl[2];
__s32 debug_enable;
__s32 hold_key_min;
__s32 hold_key_max;
__u32 work_mode;
__u32 storage_type;
normal_gpio_cfg storage_gpio[32];
__u8 storage_data[256];
} boot1_private_head_t;
typedef struct _boot1_file_head_t {
boot_file_head_t boot_head;
boot1_private_head_t prvt_head;
} boot1_file_head_t;
/* STORAGE DATA on SD loaders */
typedef struct _boot_sdcard_info_t {
__s32 card_ctrl_num;
__s32 boot_offset;
__s32 card_no[4];
__s32 speed_mode[4];
__s32 line_sel[4];
__s32 line_count[4];
} boot_sdcard_info_t;
#define BROM_MAGIC "eGON.BRM"
#define BOOT0_MAGIC "eGON.BT0"
#define BOOT1_MAGIC "eGON.BT1"
union {
boot_file_head_t boot;
boot0_file_head_t boot0;
boot1_file_head_t boot1;
brom_file_head_t brom;
} boot_hdr;
typedef enum {
ALLWINNER_UNKNOWN_LOADER=0,
ALLWINNER_SD_LOADER,
ALLWINNER_NAND_LOADER
} loader_type;
void fail(char *msg) {
perror(msg);
exit(1);
}
void pprintf(void *addr, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("%8x:\t", (unsigned)((char *)addr - (char *)&boot_hdr));
vprintf(fmt, ap);
va_end(ap);
}
void print_brom_file_head(brom_file_head_t *hdr)
{
pprintf(&hdr->magic, "Magic : %.8s\n", hdr->magic);
pprintf(&hdr->length, "Length : %u\n", hdr->length);
pprintf(&hdr->Boot_vsn, "BOOT ver : %.4s\n", hdr->Boot_vsn);
pprintf(&hdr->eGON_vsn, "eGON ver : %.4s\n", hdr->eGON_vsn);
pprintf(&hdr->platform, "Chip? : %.8s\n", hdr->platform);
}
void print_boot_file_head(boot_file_head_t *hdr)
{
pprintf(&hdr->magic, "Magic : %.8s\n", hdr->magic);
pprintf(&hdr->length, "Length : %u\n", hdr->length);
pprintf(&hdr->pub_head_size, "HSize : %u\n", hdr->pub_head_size);
pprintf(&hdr->pub_head_vsn, "HEAD ver : %.4s\n", hdr->pub_head_vsn);
pprintf(&hdr->file_head_vsn, "FILE ver : %.4s\n", hdr->file_head_vsn);
pprintf(&hdr->Boot_vsn, "BOOT ver : %.4s\n", hdr->Boot_vsn);
pprintf(&hdr->eGON_vsn, "eGON ver : %.4s\n", hdr->eGON_vsn);
pprintf(&hdr->platform, "platform : %c%c%c%c%c%c%c%c\n", hdr->platform[0], hdr->platform[1], hdr->platform[2], hdr->platform[3], hdr->platform[4], hdr->platform[5], hdr->platform[6], hdr->platform[7]);
}
void print_boot_dram_para(boot_dram_para_t *dram)
{
pprintf(&dram->dram_baseaddr, "DRAM base : %p\n", (void *)(uintptr_t)dram->dram_baseaddr);
pprintf(&dram->dram_clk, "DRAM clk : %d\n", dram->dram_clk);
pprintf(&dram->dram_type, "DRAM type : %d\n", dram->dram_type);
pprintf(&dram->dram_rank_num, "DRAM rank : %d\n", dram->dram_rank_num);
pprintf(&dram->dram_chip_density,"DRAM den : %d\n", dram->dram_chip_density);
pprintf(&dram->dram_io_width, "DRAM iow : %d\n", dram->dram_io_width);
pprintf(&dram->dram_bus_width, "DRAM busw : %d\n", dram->dram_bus_width);
pprintf(&dram->dram_cas, "DRAM cas : %d\n", dram->dram_cas);
pprintf(&dram->dram_zq, "DRAM zq : %d\n", dram->dram_zq);
pprintf(&dram->dram_odt_en, "DRAM odt : 0x%x\n", dram->dram_odt_en);
pprintf(&dram->dram_size, "DRAM size : %d\n", dram->dram_size);
pprintf(&dram->dram_tpr0, "DRAM tpr0 : 0x%x\n", dram->dram_tpr0);
pprintf(&dram->dram_tpr1, "DRAM tpr1 : 0x%x\n", dram->dram_tpr1);
pprintf(&dram->dram_tpr2, "DRAM tpr2 : 0x%x\n", dram->dram_tpr2);
pprintf(&dram->dram_tpr3, "DRAM tpr3 : 0x%x\n", dram->dram_tpr3);
pprintf(&dram->dram_tpr4, "DRAM tpr4 : 0x%x\n", dram->dram_tpr4);
pprintf(&dram->dram_tpr5, "DRAM tpr5 : 0x%x\n", dram->dram_tpr5);
pprintf(&dram->dram_emr1, "DRAM emr1 : 0x%x\n", dram->dram_emr1);
pprintf(&dram->dram_emr2, "DRAM emr2 : 0x%x\n", dram->dram_emr2);
pprintf(&dram->dram_emr3, "DRAM emr3 : 0x%x\n", dram->dram_emr3);
}
void print_normal_gpio_cfg(normal_gpio_cfg *gpio, int count)
{
int i;
for (i = 0; i < count; i++) {
if (gpio[i].port)
pprintf(&gpio[i], " GPIO %d : port=%c%d, sel=%d, pull=%d, drv=%d, data=%d, reserved=%02x,%02x\n", i, 'A'+gpio[i].port-1, gpio[i].port_num, gpio[i].mul_sel, gpio[i].pull, gpio[i].drv_level, gpio[i].data, gpio[i].reserved[0], gpio[i].reserved[1]);
}
}
void print_boot_sdcard_info(boot_sdcard_info_t *info)
{
pprintf(&info->card_ctrl_num, " CARD Ctrl Num: %d\n", info->card_ctrl_num);
pprintf(&info->boot_offset, " BOOT Offset: %08x\n", info->boot_offset);
for (int i = 0; i < 4; i++) {
if (info->card_no[i] == -1)
continue;
pprintf(&info->card_no[i], " CARD No : %d (%d)\n", info->card_no[i], i);
pprintf(&info->speed_mode[i], " Speed : %d\n", info->speed_mode[i]);
pprintf(&info->line_sel[i], " Line sel: %d\n", info->line_sel[i]);
pprintf(&info->line_count[i], " Line cnt: %d\n", info->line_count[i]);
}
}
void print_boot0_private_head(boot0_private_head_t *hdr, loader_type type)
{
pprintf(&hdr->prvt_head_size, "FHSize : %u\n", hdr->prvt_head_size);
pprintf(&hdr->prvt_head_vsn, "FILE ver : %.4s\n", hdr->prvt_head_vsn);
print_boot_dram_para(&hdr->dram_para);
pprintf(&hdr->uart_port, "UART port : %d\n", hdr->uart_port);
print_normal_gpio_cfg(hdr->uart_ctrl, 2);
pprintf(&hdr->enable_jtag, "JTAG en : %d\n", hdr->enable_jtag);
print_normal_gpio_cfg(hdr->jtag_gpio, 5);
pprintf(&hdr->storage_gpio, "STORAGE :\n");
print_normal_gpio_cfg(hdr->storage_gpio, 32);
int i = 0;
if (type == ALLWINNER_SD_LOADER) {
print_boot_sdcard_info((boot_sdcard_info_t *)hdr->storage_data);
i = sizeof(boot_sdcard_info_t);
}
for (int n = 0; i < 256; i++, n++) {
if (n % 16 == 0) {
if (n) {
printf("\n");
}
pprintf(&hdr->storage_data[i], " DATA %02x :", i);
}
printf(" %02x", hdr->storage_data[i]);
}
printf("\n");
}
void print_script(void *UNUSED(script))
{
}
void print_core_para(boot_core_para_t *core)
{
pprintf(&core->user_set_clock, "Set Clock : %d\n", core->user_set_clock);
pprintf(&core->user_set_core_vol, "Set Core Vol: %d\n", core->user_set_core_vol);
pprintf(&core->vol_threshold, "Vol Threshold: %d\n", core->vol_threshold);
}
void print_boot1_private_head(boot1_private_head_t *hdr, loader_type type)
{
pprintf(&hdr->prvt_head_size, "FHSize : %u\n", hdr->prvt_head_size);
pprintf(&hdr->prvt_head_vsn, "FILE ver : %.4s\n", hdr->prvt_head_vsn);
pprintf(&hdr->uart_port, "UART port : %d\n", hdr->uart_port);
print_normal_gpio_cfg(hdr->uart_ctrl, 2);
print_boot_dram_para(&hdr->dram_para);
print_script(&hdr->script_buf);
print_core_para(&hdr->core_para);
pprintf(&hdr->twi_port, "TWI port : %d\n", hdr->twi_port);
print_normal_gpio_cfg(hdr->twi_ctrl, 2);
pprintf(&hdr->debug_enable, "Debug : %d\n", hdr->debug_enable);
pprintf(&hdr->hold_key_min, "Hold key min : %d\n", hdr->hold_key_min);
pprintf(&hdr->hold_key_max, "Hold key max : %d\n", hdr->hold_key_max);
pprintf(&hdr->work_mode, "Work mode : %d\n", hdr->work_mode);
pprintf(&hdr->storage_type, "STORAGE :\n");
pprintf(&hdr->storage_type, " type : %d\n", hdr->storage_type);
print_normal_gpio_cfg(hdr->storage_gpio, 32);
int i = 0;
if (type == ALLWINNER_SD_LOADER) {
print_boot_sdcard_info((boot_sdcard_info_t *)hdr->storage_data);
i = sizeof(boot_sdcard_info_t);
}
for (int n = 0; i < 256; i++, n++) {
if (n % 16 == 0) {
if (n) {
printf("\n");
}
pprintf(&hdr->storage_data[i], " DATA %02x :", i);
}
printf(" %02x", hdr->storage_data[i]);
}
printf("\n");
}
void print_boot0_file_head(boot0_file_head_t *hdr, loader_type type)
{
print_boot_file_head(&hdr->boot_head);
if (strncmp((char *)hdr->boot_head.file_head_vsn, "1230", 4) == 0)
print_boot0_private_head(&hdr->prvt_head, type);
else
printf("Unknown boot0 header version\n");
}
void print_boot1_file_head(boot1_file_head_t *hdr, loader_type type)
{
print_boot_file_head(&hdr->boot_head);
if (strncmp((char *)hdr->boot_head.file_head_vsn, "1230", 4) == 0)
print_boot1_private_head(&hdr->prvt_head, type);
else
printf("Unknown boot0 header version\n");
}
static void usage(const char *cmd)
{
puts("sunxi-bootinfo " VERSION "\n");
printf("Usage: %s [<filename>]\n", cmd);
printf(" With no <filename> given, will read from stdin instead\n");
}
int main(int argc, char * argv[])
{
FILE *in = stdin;
loader_type type = ALLWINNER_UNKNOWN_LOADER;
if (argc > 1 && strcmp(argv[1], "--type=sd") == 0) {
type = ALLWINNER_SD_LOADER;
argc--;
argv++;
}
if (argc > 1 && strcmp(argv[1], "--type=nand") == 0) {
type = ALLWINNER_NAND_LOADER;
argc--;
argv++;
}
if (argc > 1) {
in = fopen(argv[1], "rb");
if (!in) {
if (*argv[1] == '-')
usage(argv[0]);
fail("open input");
}
}
int len;
len = fread(&boot_hdr, 1, sizeof(boot_hdr), in);
if (len < (int)sizeof(boot_file_head_t))
fail("Failed to read header:");
if (strncmp((char *)boot_hdr.boot.magic, BOOT0_MAGIC, strlen(BOOT0_MAGIC)) == 0) {
print_boot0_file_head(&boot_hdr.boot0, type);
} else if (strncmp((char *)boot_hdr.boot.magic, BOOT1_MAGIC, strlen(BOOT1_MAGIC)) == 0) {
print_boot1_file_head(&boot_hdr.boot1, type);
} else if (strncmp((char *)boot_hdr.boot.magic, BROM_MAGIC, strlen(BROM_MAGIC)) == 0) {
print_brom_file_head(&boot_hdr.brom);
} else {
fail("Invalid magic\n");
}
return 0;
}