bootinfo.c 12.4 KB
Newer Older
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
/*
 * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
 *
 * 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>
26
#include <stdarg.h>
27

28
#include "common.h"
29
#include "types.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

/* 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;

47
48
49
50
51
52
53
54
55
56
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;

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
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];
99
    __u8 storage_data[256];
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
} 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];
129
    __u8 storage_data[256];
130
131
132
133
134
135
136
} 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;

137
/* STORAGE DATA on SD loaders */
138
139
140
141
142
143
144
145
146
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;

147
#define BROM_MAGIC                     "eGON.BRM"
148
149
150
#define BOOT0_MAGIC                     "eGON.BT0"
#define BOOT1_MAGIC                     "eGON.BT1"

151
152
153
154
155
156
157
union {
	boot_file_head_t boot;
	boot0_file_head_t boot0;
	boot1_file_head_t boot1;
	brom_file_head_t brom;
} boot_hdr;

158
159
160
161
162
163
typedef enum {
	ALLWINNER_UNKNOWN_LOADER=0,
	ALLWINNER_SD_LOADER,
	ALLWINNER_NAND_LOADER
} loader_type;

164
165
166
167
168
void fail(char *msg) {
	perror(msg);
	exit(1);
}

169
170
171
172
173
174
175
176
177
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);
}

178
179
void print_brom_file_head(brom_file_head_t *hdr)
{
180
181
182
183
184
	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);
185
186
}

187
188
void print_boot_file_head(boot_file_head_t *hdr)
{
189
190
191
192
193
194
195
196
	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]);
197
198
199
200
}

void print_boot_dram_para(boot_dram_para_t *dram)
{
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	pprintf(&dram->dram_baseaddr,	"DRAM base : %p\n", (void *)(long)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);
221
222
223
224
225
226
227
}

void print_normal_gpio_cfg(normal_gpio_cfg *gpio, int count)
{
	int i;
	for (i = 0; i < count; i++) {
		if (gpio[i].port)
228
			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]);
229
230
	}
}
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

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)
248
{
249
250
	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);
251
	print_boot_dram_para(&hdr->dram_para);
252
	pprintf(&hdr->uart_port,	"UART port : %d\n", hdr->uart_port);
253
	print_normal_gpio_cfg(hdr->uart_ctrl, 2);
254
	pprintf(&hdr->enable_jtag,	"JTAG en   : %d\n", hdr->enable_jtag);
255
	print_normal_gpio_cfg(hdr->jtag_gpio, 5);
256
	pprintf(&hdr->storage_gpio,	"STORAGE   :\n");
257
	print_normal_gpio_cfg(hdr->storage_gpio, 32);
258
259
260
261
262
263
264
265
	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) {
266
267
				printf("\n");
			}
268
			pprintf(&hdr->storage_data[i], " DATA %02x  :", i);
269
		}
270
		printf(" %02x", hdr->storage_data[i]);
271
272
273
274
	}
	printf("\n");
}

275
void print_script(void *UNUSED(script))
276
277
278
279
280
{
}

void print_core_para(boot_core_para_t *core)
{
281
282
283
	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);
284
285
}

286
void print_boot1_private_head(boot1_private_head_t *hdr, loader_type type)
287
{
288
289
290
	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);
291
292
293
294
	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);
295
	pprintf(&hdr->twi_port,		"TWI port  : %d\n", hdr->twi_port);
296
	print_normal_gpio_cfg(hdr->twi_ctrl, 2);
297
298
299
300
	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);
301
302
303
	pprintf(&hdr->storage_type,	"STORAGE   :\n");
	pprintf(&hdr->storage_type,	" type   : %d\n", hdr->storage_type);
	print_normal_gpio_cfg(hdr->storage_gpio, 32);
304
305
306
307
308
309
310
311
	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) {
312
313
				printf("\n");
			}
314
			pprintf(&hdr->storage_data[i], " DATA %02x  :", i);
315
		}
316
		printf(" %02x", hdr->storage_data[i]);
317
318
319
320
	}
	printf("\n");
}

321
void print_boot0_file_head(boot0_file_head_t *hdr, loader_type type)
322
323
324
{
	print_boot_file_head(&hdr->boot_head);
	if (strncmp((char *)hdr->boot_head.file_head_vsn, "1230", 4) == 0)
325
		print_boot0_private_head(&hdr->prvt_head, type);
326
327
328
329
	else
		printf("Unknown boot0 header version\n");
}

330
void print_boot1_file_head(boot1_file_head_t *hdr, loader_type type)
331
332
333
{
	print_boot_file_head(&hdr->boot_head);
	if (strncmp((char *)hdr->boot_head.file_head_vsn, "1230", 4) == 0)
334
		print_boot1_private_head(&hdr->prvt_head, type);
335
336
337
338
	else
		printf("Unknown boot0 header version\n");
}

339
340
341
342
343
344
345
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");
}

346
347
348
int main(int argc, char * argv[])
{
	FILE *in = stdin;
349
350
351
352
353
354
355
356
357
358
359
	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++;
	}
360
361
	if (argc > 1) {
		in = fopen(argv[1], "rb");
362
363
364
365
366
		if (!in) {
			if (*argv[1] == '-')
				usage(argv[0]);
			fail("open input");
		}
367
368
369
	}
	int len;

370
	len = fread(&boot_hdr, 1, sizeof(boot_hdr), in);
371
372
	if (len < (int)sizeof(boot_file_head_t))
		fail("Failed to read header:");
373
	if (strncmp((char *)boot_hdr.boot.magic, BOOT0_MAGIC, strlen(BOOT0_MAGIC)) == 0) {
374
		print_boot0_file_head(&boot_hdr.boot0, type);
375
	} else if (strncmp((char *)boot_hdr.boot.magic, BOOT1_MAGIC, strlen(BOOT1_MAGIC)) == 0) {
376
		print_boot1_file_head(&boot_hdr.boot1, type);
377
378
	} else if (strncmp((char *)boot_hdr.boot.magic, BROM_MAGIC, strlen(BROM_MAGIC)) == 0) {
		print_brom_file_head(&boot_hdr.brom);
379
380
381
382
383
384
	} else {
		fail("Invalid magic\n");
	}

	return 0;
}