diff --git a/Makefile b/Makefile index 36e7383..fb52c86 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC = gcc CFLAGS = -g -O0 -Wall -Wextra CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L -TOOLS = fexc bin2fex fex2bin fel +TOOLS = fexc bin2fex fex2bin bootinfo fel MISC_TOOLS = phoenix_info @@ -21,10 +21,12 @@ $(TOOLS): Makefile common.h fex2bin bin2fex: fexc ln -s $< $@ -fexc: script.h script.c \ +fexc: fexc.h script.h script.c \ script_bin.h script_bin.c \ script_fex.h script_fex.c +bootinfo: bootinfo.c + LIBUSB = libusb-1.0 LIBUSB_CFLAGS = `pkg-config --cflags $(LIBUSB)` LIBUSB_LIBS = `pkg-config --libs $(LIBUSB)` @@ -32,7 +34,7 @@ LIBUSB_LIBS = `pkg-config --libs $(LIBUSB)` fel: fel.c $(CC) $(CFLAGS) $(LIBUSB_CFLAGS) $(LDFLAGS) -o $@ $(filter %.c,$^) $(LIBS) $(LIBUSB_LIBS) -%: %.c %.h +%: %.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(filter %.c,$^) $(LIBS) .gitignore: Makefile diff --git a/README b/README index fcb7eb9..9e77355 100644 --- a/README +++ b/README @@ -26,6 +26,9 @@ fel: th CPU. You activate FEL mode by pushing the usboot/recovery button at poweron. +bootinfo: + Dump information from Allwinner boot files (boot0/boot1) + phoenix_info: gives information about a phoenix image created by the phoenixcard utility and optionally extracts the embedded boot diff --git a/bootinfo.c b/bootinfo.c new file mode 100644 index 0000000..378e473 --- /dev/null +++ b/bootinfo.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2012 Henrik Nordstrom + * + * 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 +#include +#include +#include + + +typedef unsigned char u8; +typedef unsigned char __u8; +typedef unsigned int u32; +typedef unsigned int __u32; +typedef signed int __s32; + +/* 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 _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]; + char 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]; + char 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; + +/* Not sure where this is, but should be in STORAGE DATA somewhere */ +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 BOOT0_MAGIC "eGON.BT0" +#define BOOT1_MAGIC "eGON.BT1" + +void fail(char *msg) { + perror(msg); + exit(1); +} + +void print_boot_file_head(boot_file_head_t *hdr) +{ + printf("Magic : %.8s\n", hdr->magic); + printf("Length : %u\n", hdr->length); + printf("HSize : %u\n", hdr->pub_head_size); + printf("HEAD ver : %.4s\n", hdr->pub_head_vsn); + printf("FILE ver : %.4s\n", hdr->file_head_vsn); + printf("BOOT ver : %.4s\n", hdr->Boot_vsn); + printf("eGON ver : %.4s\n", hdr->eGON_vsn); + printf("platform : %.8s\n", hdr->platform); +} + +void print_boot_dram_para(boot_dram_para_t *dram) +{ + printf("DRAM base : %p\n", (void *)(long)dram->dram_baseaddr); + printf("DRAM clk : %d\n", dram->dram_clk); + printf("DRAM type : %d\n", dram->dram_type); + printf("DRAM rank : %d\n", dram->dram_rank_num); + printf("DRAM den : %d\n", dram->dram_chip_density); + printf("DRAM iow : %d\n", dram->dram_io_width); + printf("DRAM busw : %d\n", dram->dram_bus_width); + printf("DRAM cas : %d\n", dram->dram_cas); + printf("DRAM zq : %d\n", dram->dram_zq); + printf("DRAM odt : 0x%x\n", dram->dram_odt_en); + printf("DRAM size : %d\n", dram->dram_size); + printf("DRAM tpr0 : 0x%x\n", dram->dram_tpr0); + printf("DRAM tpr1 : 0x%x\n", dram->dram_tpr1); + printf("DRAM tpr2 : 0x%x\n", dram->dram_tpr2); + printf("DRAM tpr3 : 0x%x\n", dram->dram_tpr3); + printf("DRAM tpr4 : 0x%x\n", dram->dram_tpr4); + printf("DRAM tpr5 : 0x%x\n", dram->dram_tpr5); + printf("DRAM emr1 : 0x%x\n", dram->dram_emr1); + printf("DRAM emr2 : 0x%x\n", dram->dram_emr2); + printf("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) + printf(" 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_boot0_private_head(boot0_private_head_t *hdr) +{ + printf("FHSize : %u\n", hdr->prvt_head_size); + printf("FILE ver : %.4s\n", hdr->prvt_head_vsn); + print_boot_dram_para(&hdr->dram_para); + printf("UART port : %d\n", hdr->uart_port); + print_normal_gpio_cfg(hdr->uart_ctrl, 2); + printf("JTAG en : %d\n", hdr->enable_jtag); + print_normal_gpio_cfg(hdr->jtag_gpio, 5); + printf("STORAGE :\n"); + print_normal_gpio_cfg(hdr->storage_gpio, 2); + int i; + for (i = 0; i < 256; i++) { + if (i % 16 == 0) { + if (i) { + printf("\n"); + } + printf(" DATA %02x :", i); + } + printf(" %02x", (u8)hdr->storage_data[i]); + } + printf("\n"); +} + +void print_script(void *script) +{ +} + +void print_core_para(boot_core_para_t *core) +{ + printf("Set Clock : %d\n", core->user_set_clock); + printf("Set Core Vol: %d\n", core->user_set_core_vol); + printf("Vol Threshold: %d\n", core->vol_threshold); +} + +void print_boot1_private_head(boot1_private_head_t *hdr) +{ + printf("FHSize : %u\n", hdr->prvt_head_size); + printf("FILE ver : %.4s\n", hdr->prvt_head_vsn); + printf("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); + printf("TWI port : %d\n", hdr->twi_port); + print_normal_gpio_cfg(hdr->twi_ctrl, 2); + printf("Debug : %d\n", hdr->debug_enable); + printf("Hold key min : %d\n", hdr->hold_key_min); + printf("Hold key max : %d\n", hdr->hold_key_max); + printf("Work mode : %d\n", hdr->work_mode); + printf("Storage : %d\n", hdr->storage_type); + int i; + for (i = 0; i < 256; i++) { + if (i % 16 == 0) { + if (i) { + printf("\n"); + } + printf(" DATA %02x :", i); + } + printf(" %02x", (u8)hdr->storage_data[i]); + } + printf("\n"); +} + +void print_boot0_file_head(boot0_file_head_t *hdr) +{ + 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); + else + printf("Unknown boot0 header version\n"); +} + +void print_boot1_file_head(boot1_file_head_t *hdr) +{ + 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); + else + printf("Unknown boot0 header version\n"); +} + +int main(int argc, char * argv[]) +{ + FILE *in = stdin; + if (argc > 1) { + in = fopen(argv[1], "rb"); + if (!in) + fail("open input: "); + } + union { + boot_file_head_t boot; + boot0_file_head_t boot0; + boot1_file_head_t boot1; + } hdr; + int len; + + len = fread(&hdr, 1, sizeof(hdr), stdin); + if (len < (int)sizeof(boot_file_head_t)) + fail("Failed to read header:"); + if (strncmp((char *)hdr.boot.magic, BOOT0_MAGIC, strlen(BOOT0_MAGIC)) == 0) { + print_boot0_file_head(&hdr.boot0); + } else if (strncmp((char *)hdr.boot.magic, BOOT1_MAGIC, strlen(BOOT1_MAGIC)) == 0) { + print_boot1_file_head(&hdr.boot1); + } else { + fail("Invalid magic\n"); + } + + return 0; +}