From e09c1e3d43665d04ae0ce2f288ba695b5abc3622 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sat, 19 May 2012 13:55:33 +0200 Subject: [PATCH] mkimxboot: add support for more target and variants Add creative zen x-fi 2/3 and add a variant mechanism Change-Id: Ic2ee82a4238a87c2eb5d72b8309650d9a280325f --- rbutil/mkimxboot/Makefile | 2 +- rbutil/mkimxboot/dualboot.c | 10 ++ rbutil/mkimxboot/dualboot.h | 2 + rbutil/mkimxboot/dualboot/Makefile | 10 +- rbutil/mkimxboot/dualboot/dualboot.S | 20 ++++ rbutil/mkimxboot/main.c | 56 ++++++++++- rbutil/mkimxboot/mkimxboot.c | 134 +++++++++++++++++++++------ rbutil/mkimxboot/mkimxboot.h | 29 +++++- 8 files changed, 228 insertions(+), 35 deletions(-) diff --git a/rbutil/mkimxboot/Makefile b/rbutil/mkimxboot/Makefile index 942ceb9ca7..41581c312d 100644 --- a/rbutil/mkimxboot/Makefile +++ b/rbutil/mkimxboot/Makefile @@ -8,7 +8,7 @@ # We use the SB code available in the Rockbox utils/sbtools directory IMXTOOLS_DIR=../../utils/imxtools/ CFLAGS += -I$(IMXTOOLS_DIR) -Wall -CFLAGS += -std=c99 +CFLAGS += -std=c99 -g OUTPUT = mkimxboot diff --git a/rbutil/mkimxboot/dualboot.c b/rbutil/mkimxboot/dualboot.c index 67ab56d302..29e18eddf7 100644 --- a/rbutil/mkimxboot/dualboot.c +++ b/rbutil/mkimxboot/dualboot.c @@ -14,3 +14,13 @@ unsigned char dualboot_fuzeplus[152] = { 0x10, 0x86, 0x01, 0x80, 0xc0, 0x40, 0x04, 0x80, 0x70, 0x64, 0x08, 0x00, 0x80, 0x1a, 0x06, 0x00, 0x00, 0x41, 0x04, 0x80, 0x01, 0x00, 0x77, 0x3e }; +unsigned char dualboot_zenxfi2[36] = { + 0x18, 0x20, 0x9f, 0xe5, 0x00, 0x20, 0x92, 0xe5, 0x01, 0x09, 0x12, 0xe3, 0x00, 0x00, 0xa0, 0x03, + 0x1e, 0xff, 0x2f, 0x01, 0x00, 0x00, 0x81, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, + 0x00, 0x86, 0x01, 0x80 +}; +unsigned char dualboot_zenxfi3[36] = { + 0x18, 0x20, 0x9f, 0xe5, 0x00, 0x20, 0x92, 0xe5, 0x80, 0x00, 0x12, 0xe3, 0x00, 0x00, 0xa0, 0x03, + 0x1e, 0xff, 0x2f, 0x01, 0x00, 0x00, 0x81, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, + 0x20, 0x86, 0x01, 0x80 +}; diff --git a/rbutil/mkimxboot/dualboot.h b/rbutil/mkimxboot/dualboot.h index 78efb8170d..272e257996 100644 --- a/rbutil/mkimxboot/dualboot.h +++ b/rbutil/mkimxboot/dualboot.h @@ -1,3 +1,5 @@ /* Generated by bin2c */ extern unsigned char dualboot_fuzeplus[152]; +extern unsigned char dualboot_zenxfi2[36]; +extern unsigned char dualboot_zenxfi3[36]; diff --git a/rbutil/mkimxboot/dualboot/Makefile b/rbutil/mkimxboot/dualboot/Makefile index fa5f341b6d..6386b7c622 100644 --- a/rbutil/mkimxboot/dualboot/Makefile +++ b/rbutil/mkimxboot/dualboot/Makefile @@ -4,8 +4,8 @@ CROSS_PREFIX=arm-elf-eabi # adding a new target. mkimxboot.c also needs to be edited to refer to these # new images. -BOOTOBJS = dualboot_fuzeplus.o -BOOTBINS = dualboot_fuzeplus.arm-bin +BOOTOBJS = dualboot_fuzeplus.o dualboot_zenxfi2.o dualboot_zenxfi3.o +BOOTBINS = dualboot_fuzeplus.arm-bin dualboot_zenxfi2.arm-bin dualboot_zenxfi3.arm-bin all: ../dualboot.h ../dualboot.c @@ -14,6 +14,12 @@ all: ../dualboot.h ../dualboot.c dualboot_fuzeplus.o: dualboot.S $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DSANSA_FUZEPLUS -c -o dualboot_fuzeplus.o dualboot.S +dualboot_zenxfi2.o: dualboot.S + $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DCREATIVE_ZENXFI2 -c -o dualboot_zenxfi2.o dualboot.S + +dualboot_zenxfi3.o: dualboot.S + $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DCREATIVE_ZENXFI3 -c -o dualboot_zenxfi3.o dualboot.S + # Rules for the ARM code embedded in mkamsboot - assemble, link, then extract # the binary code and finally convert to .h for building in mkamsboot diff --git a/rbutil/mkimxboot/dualboot/dualboot.S b/rbutil/mkimxboot/dualboot/dualboot.S index 4002167929..ed91012199 100644 --- a/rbutil/mkimxboot/dualboot/dualboot.S +++ b/rbutil/mkimxboot/dualboot/dualboot.S @@ -65,6 +65,26 @@ power_down: ldr r1, =0x3E770001 @ unlock key + power down str r1, [r0] b power_down +#elif defined(CREATIVE_ZENXFI2) + /* If select key is hold, return so that the OF can boot */ + ldr r2, =0x80018600 @ HW_PINCTRL_DIN0 + ldr r2, [r2] + tst r2, #0x4000 @ bit 14, active low + moveq r0, #0 @ return 0, continue boot + bxeq lr + str r0, [r1] + mov r0, #1 + bx lr +#elif defined(CREATIVE_ZENXFI3) + /* If volume down key is hold, return so that the OF can boot */ + ldr r2, =0x80018620 @ HW_PINCTRL_DIN2 + ldr r2, [r2] + tst r2, #0x80 @ bit 7, active low + moveq r0, #0 @ return 0, continue boot + bxeq lr + str r0, [r1] + mov r0, #1 + bx lr #else #error No target defined ! #endif diff --git a/rbutil/mkimxboot/main.c b/rbutil/mkimxboot/main.c index 95fc226db1..68387c25c0 100644 --- a/rbutil/mkimxboot/main.c +++ b/rbutil/mkimxboot/main.c @@ -25,6 +25,22 @@ #include #include "mkimxboot.h" +struct imx_variant_t +{ + const char *name; + enum imx_firmware_variant_t variant; +}; + +struct imx_variant_t imx_variants[] = +{ + { "default", VARIANT_DEFAULT }, + { "zenxfi2-recovery", VARIANT_ZENXFI2_RECOVERY }, + { "zenxfi2-nand", VARIANT_ZENXFI2_NAND }, + { "zenxfi2-sd", VARIANT_ZENXFI2_SD }, +}; + +#define NR_VARIANTS sizeof(imx_variants) / sizeof(imx_variants[0]) + static void usage(void) { printf("Usage: elftosb [options | file]...\n"); @@ -35,6 +51,17 @@ static void usage(void) printf(" -b \tSet boot file\n"); printf(" -d/--debug\tEnable debug output\n"); printf(" -t \tSet type (dualboot, singleboot, recovery)\n"); + printf(" -v \tSet variant\n"); + printf(" -x\t\tDump device informations\n"); + printf("Supported variants: (default is standard)\n"); + printf(" "); + for(size_t i = 0; i < NR_VARIANTS; i++) + { + if(i != 0) + printf(", "); + printf("%s", imx_variants[i].name); + } + printf("\n"); printf("By default a dualboot image is built\n"); exit(1); } @@ -44,6 +71,7 @@ int main(int argc, char *argv[]) char *infile = NULL; char *outfile = NULL; char *bootfile = NULL; + enum imx_firmware_variant_t variant = VARIANT_DEFAULT; enum imx_output_type_t type = IMX_DUALBOOT; bool debug = false; @@ -60,10 +88,12 @@ int main(int argc, char *argv[]) {"boot-file", required_argument, 0, 'b'}, {"debug", no_argument, 0, 'd'}, {"type", required_argument, 0, 't'}, + {"variant", required_argument, 0, 'v'}, + {"dev-info", no_argument, 0, 'x'}, {0, 0, 0, 0} }; - int c = getopt_long(argc, argv, "?di:o:b:t:", long_options, NULL); + int c = getopt_long(argc, argv, "?di:o:b:t:v:x", long_options, NULL); if(c == -1) break; switch(c) @@ -98,6 +128,28 @@ int main(int argc, char *argv[]) return 1; } break; + case 'v': + { + for(size_t i = 0; i < NR_VARIANTS; i++) + { + if(strcmp(optarg, imx_variants[i].name) == 0) + { + variant = imx_variants[i].variant; + goto Lok; + } + } + printf("Invalid variant '%s'\n", optarg); + return 1; + + Lok: + break; + } + case 'x': + dump_imx_dev_info(""); + printf("variant mapping:\n"); + for(int i = 0; i < sizeof(imx_variants) / sizeof(imx_variants[0]); i++) + printf(" %s -> variant=%d\n", imx_variants[i].name, imx_variants[i].variant); + break; default: abort(); } @@ -125,8 +177,10 @@ int main(int argc, char *argv[]) } struct imx_option_t opt; + memset(&opt, 0, sizeof(opt)); opt.debug = debug; opt.output = type; + opt.fw_variant = variant; enum imx_error_t err = mkimxboot(infile, bootfile, outfile, opt); printf("Result: %d\n", err); return 0; diff --git a/rbutil/mkimxboot/mkimxboot.c b/rbutil/mkimxboot/mkimxboot.c index 6f90924c9a..8806167078 100644 --- a/rbutil/mkimxboot/mkimxboot.c +++ b/rbutil/mkimxboot/mkimxboot.c @@ -26,20 +26,22 @@ #include "dualboot.h" #include "md5.h" -/* Supported models */ -enum imx_model_t +struct imx_fw_variant_desc_t { - MODEL_UNKNOWN = -1, - MODEL_FUZEPLUS = 0, - /* new models go here */ - - NUM_MODELS + /* Offset within file */ + size_t offset; + /* Total size of the firmware */ + size_t size; }; struct imx_md5sum_t { - int model; + /* Device model */ + enum imx_model_t model; + /* md5sum of the file */ char *md5sum; + /* Variant descriptions */ + struct imx_fw_variant_desc_t fw_variants[VARIANT_COUNT]; }; struct imx_model_desc_t @@ -66,9 +68,38 @@ struct imx_model_desc_t uint32_t bootloader_addr; }; +static const char *imx_fw_variant[] = +{ + [VARIANT_DEFAULT] = "default", + [VARIANT_ZENXFI2_RECOVERY] = "ZEN X-Fi2 Recovery", + [VARIANT_ZENXFI2_NAND] = "ZEN X-Fi2 NAND", + [VARIANT_ZENXFI2_SD] = "ZEN X-Fi2 eMMC/SD", +}; + static const struct imx_md5sum_t imx_sums[] = { - { MODEL_FUZEPLUS, "c3e27620a877dc6b200b97dcb3e0ecc7" }, /* Version 2.38.6 */ + { + /* Version 2.38.6 */ + MODEL_FUZEPLUS, "c3e27620a877dc6b200b97dcb3e0ecc7", + { [VARIANT_DEFAULT] = { 0, 34652624 } } + }, + { + /* Version 1.23.01e */ + MODEL_ZENXFI2, "e37e2c24abdff8e624d0a29f79157850", + }, + { + /* Version 1.23.01e */ + MODEL_ZENXFI2, "2beff2168212d332f13cfc36ca46989d", + { [VARIANT_ZENXFI2_RECOVERY] = { 0x93010, 684192}, + [VARIANT_ZENXFI2_NAND] = { 0x13a0b0, 42410704 }, + [VARIANT_ZENXFI2_SD] = { 0x29ac380, 42304208 } + } + }, + { + /* Version 1.00.22e */ + MODEL_ZENXFI3, "658a24eeef5f7186ca731085d8822a87", + { [VARIANT_DEFAULT] = {0, 18110576} } + }, }; static struct crypto_key_t zero_key = @@ -79,8 +110,12 @@ static struct crypto_key_t zero_key = static const struct imx_model_desc_t imx_models[] = { - [MODEL_FUZEPLUS] = { "Fuze+", dualboot_fuzeplus, sizeof(dualboot_fuzeplus), "fuz+", 72, + [MODEL_FUZEPLUS] = { "Fuze+", dualboot_fuzeplus, sizeof(dualboot_fuzeplus), "fuz+", 72, 1, &zero_key, 0, 0x40000000 }, + [MODEL_ZENXFI2] = {"Zen X-Fi2", dualboot_zenxfi2, sizeof(dualboot_zenxfi2), "zxf2", 82, + 1, &zero_key, 0, 0x40000000 }, + [MODEL_ZENXFI3] = {"Zen X-Fi3", dualboot_zenxfi3, sizeof(dualboot_zenxfi3), "zxf3", 83, + 1, &zero_key, 0, 0x40000000 }, }; #define NR_IMX_SUMS (sizeof(imx_sums) / sizeof(imx_sums[0])) @@ -212,7 +247,8 @@ static enum imx_error_t patch_std_zero_host_play(int jump_before, int model, } } -static enum imx_error_t patch_firmware(int model, enum imx_output_type_t type, +static enum imx_error_t patch_firmware(enum imx_model_t model, + enum imx_firmware_variant_t variant, enum imx_output_type_t type, struct sb_file_t *sb_file, void *boot, size_t boot_sz) { switch(model) @@ -221,6 +257,23 @@ static enum imx_error_t patch_firmware(int model, enum imx_output_type_t type, /* The Fuze+ uses the standard ____, host, play sections, patch after third * call in ____ section */ return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz); + case MODEL_ZENXFI3: + /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third + * call in ____ section. Although sections names use the S variant, they are standard. */ + return patch_std_zero_host_play(3, model, type, sb_file, boot, boot_sz); + case MODEL_ZENXFI2: + /* The ZEN X-Fi2 has two types of firmware: recovery and normal. + * Normal uses the standard ___, host, play sections and recovery only ____ */ + switch(variant) + { + case VARIANT_ZENXFI2_RECOVERY: + case VARIANT_ZENXFI2_NAND: + case VARIANT_ZENXFI2_SD: + return patch_std_zero_host_play(1, model, type, sb_file, boot, boot_sz); + default: + return IMX_DONT_KNOW_HOW_TO_PATCH; + } + break; default: return IMX_DONT_KNOW_HOW_TO_PATCH; } @@ -247,26 +300,38 @@ static uint32_t get_uint32be(unsigned char *p) return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } +void dump_imx_dev_info(const char *prefix) +{ + printf("%smkimxboot models:\n", prefix); + for(int i = 0; i < NR_IMX_MODELS; i++) + { + printf("%s %s: idx=%d rb_model=%s rb_num=%d\n", prefix, + imx_models[i].model_name, i, imx_models[i].rb_model_name, + imx_models[i].rb_model_num); + } + printf("%smkimxboot variants:\n", prefix); + for(int i = 0; i < VARIANT_COUNT; i++) + { + printf("%s %d: %s\n", prefix, i, imx_fw_variant[i]); + } + printf("%smkimxboot mapping:\n", prefix); + for(int i = 0; i < NR_IMX_SUMS; i++) + { + printf("%s md5sum=%s -> idx=%d\n", prefix, imx_sums[i].md5sum, + imx_sums[i].model); + for(int j = 0; j < VARIANT_COUNT; j++) + if(imx_sums[i].fw_variants[j].size) + printf("%s variant=%d -> offset=%#x size=%#x\n", prefix, + j, (unsigned)imx_sums[i].fw_variants[j].offset, + (unsigned)imx_sums[i].fw_variants[j].size); + } +} + enum imx_error_t mkimxboot(const char *infile, const char *bootfile, const char *outfile, struct imx_option_t opt) { /* Dump tables */ - do - { - printf("[INFO] mkimxboot models:\n"); - for(int i = 0; i < NR_IMX_MODELS; i++) - { - printf("[INFO] %s: idx=%d rb_model=%s rb_num=%d\n", - imx_models[i].model_name, i, imx_models[i].rb_model_name, - imx_models[i].rb_model_num); - } - printf("[INFO] mkimxboot mapping:\n"); - for(int i = 0; i < NR_IMX_SUMS; i++) - { - printf("[INFO] md5sum=%s -> idx=%d\n", imx_sums[i].md5sum, - imx_sums[i].model); - } - }while(0); + dump_imx_dev_info("[INFO] "); /* compute MD5 sum of the file */ uint8_t file_md5sum[16]; do @@ -298,7 +363,8 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, printf("[INFO] MD5 sum of the file: "); print_hex(file_md5sum, 16, true); /* find model */ - int model; + enum imx_model_t model; + int md5_idx; do { int i = 0; @@ -327,6 +393,7 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, return IMX_NO_MATCH; } model = imx_sums[i].model; + md5_idx = i; }while(0); printf("[INFO] File is for model %d (%s)\n", model, imx_models[model].model_name); /* load rockbox file */ @@ -385,11 +452,18 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, struct sb_file_t *sb_file; do { + if(imx_sums[md5_idx].fw_variants[opt.fw_variant].size == 0) + { + printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]); + free(boot); + return IMX_VARIANT_MISMATCH; + } enum sb_error_t err; g_debug = opt.debug; clear_keys(); add_keys(imx_models[model].keys, imx_models[model].nr_keys); - sb_file = sb_read_file(infile, false, NULL, &imx_printf, &err); + sb_file = sb_read_file_ex(infile, imx_sums[md5_idx].fw_variants[opt.fw_variant].offset, + imx_sums[md5_idx].fw_variants[opt.fw_variant].size, false, NULL, &imx_printf, &err); if(sb_file == NULL) { clear_keys(); @@ -398,7 +472,7 @@ enum imx_error_t mkimxboot(const char *infile, const char *bootfile, } }while(0); /* produce file */ - enum imx_error_t ret = patch_firmware(model, opt.output, sb_file, boot + 8, boot_size - 8); + enum imx_error_t ret = patch_firmware(model, opt.fw_variant, opt.output, sb_file, boot + 8, boot_size - 8); if(ret == IMX_SUCCESS) ret = sb_write_file(sb_file, outfile); diff --git a/rbutil/mkimxboot/mkimxboot.h b/rbutil/mkimxboot/mkimxboot.h index 4ee1ca20cf..5be87b31e0 100644 --- a/rbutil/mkimxboot/mkimxboot.h +++ b/rbutil/mkimxboot/mkimxboot.h @@ -40,7 +40,8 @@ enum imx_error_t IMX_BOOT_MISMATCH = -6, IMX_BOOT_CHECKSUM_ERROR = -7, IMX_DONT_KNOW_HOW_TO_PATCH = -8, - IMX_FIRST_SB_ERROR = -9, + IMX_VARIANT_MISMATCH = -9, + IMX_FIRST_SB_ERROR = -10, }; enum imx_output_type_t @@ -50,12 +51,38 @@ enum imx_output_type_t IMX_SINGLEBOOT = 2, }; +/* Supported models */ +enum imx_model_t +{ + MODEL_UNKNOWN = -1, + MODEL_FUZEPLUS = 0, + MODEL_ZENXFI2 = 1, + MODEL_ZENXFI3 = 2, + /* new models go here */ + + NUM_MODELS +}; + +/* Supported firmware variants */ +enum imx_firmware_variant_t +{ + VARIANT_DEFAULT = 0, + /* For the Creative ZEN X-Fi2 */ + VARIANT_ZENXFI2_NAND, + VARIANT_ZENXFI2_SD, + VARIANT_ZENXFI2_RECOVERY, + /* Last */ + VARIANT_COUNT +}; + struct imx_option_t { bool debug; enum imx_output_type_t output; + enum imx_firmware_variant_t fw_variant; }; +void dump_imx_dev_info(const char *prefix); enum imx_error_t mkimxboot(const char *infile, const char *bootfile, const char *outfile, struct imx_option_t opt);