mirror of
https://github.com/linux-sunxi/sunxi-tools.git
synced 2024-11-23 01:46:44 +08:00
4564e7822b
Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
385 lines
12 KiB
C
385 lines
12 KiB
C
/*
|
|
* (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>
|
|
#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;
|
|
}
|