From 2e0c558064ad6c92624a0a826721a83321b227af Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 22 Oct 2013 00:48:33 +0200 Subject: Introduce rbutil/mkzenboot, a replacement for tools/mkzenboot The old tools/mkzenboot has a number of problems: very hard to maintain, poor integration with rbutil. Restart from scratch by recycling all the crypto and descrambling code, rewrite the actual firmware modification part to handle all scenarios in a much clearer way. The code is ready to be integrated into Rockbox Utility, by using the very similar interface to mkimxboot. I copied all the keys from the old mkzenboot, so it can potentially support the older Creative ports, but since this is untested, I prefer not do so at the moment. However, I did add a "mixed" boot option to support the dualboot style used in the older ports. Change-Id: I80cfc48fa78187baa1b1692e8a30ec7137cea37b --- rbutil/mkzenboot/dualboot/dualboot.c | 134 +++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 rbutil/mkzenboot/dualboot/dualboot.c (limited to 'rbutil/mkzenboot/dualboot/dualboot.c') diff --git a/rbutil/mkzenboot/dualboot/dualboot.c b/rbutil/mkzenboot/dualboot/dualboot.c new file mode 100644 index 0000000000..d0587fa65d --- /dev/null +++ b/rbutil/mkzenboot/dualboot/dualboot.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "regs-pinctrl.h" +#include "regs-power.h" +#include "regs-lradc.h" + +typedef unsigned long uint32_t; + +// target specific boot decision +enum boot_t +{ + BOOT_STOP, /* power down */ + BOOT_ROCK, /* boot to Rockbox */ + BOOT_OF, /* boot to OF */ +}; + +/** + * Helper functions + */ + +static inline int __attribute__((always_inline)) read_gpio(int bank, int pin) +{ + return (HW_PINCTRL_DINn(bank) >> pin) & 1; +} + +static inline int __attribute__((always_inline)) read_pswitch(void) +{ +#if IMX233_SUBTARGET >= 3700 + return BF_RD(POWER_STS, PSWITCH); +#else + return BF_RD(DIGCTL_STATUS, PSWITCH); +#endif +} + +/* only works for channels <=7, always divide by 2, never accumulates */ +static inline void __attribute__((always_inline)) setup_lradc(int src) +{ + BF_CLR(LRADC_CTRL0, SFTRST); + BF_CLR(LRADC_CTRL0, CLKGATE); + /* don't bother changing the source, we are early enough at boot so that + * channel x is mapped to source x */ + HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE); + BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src); +} + +#define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x) +#define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x)) + +static inline int __attribute__((always_inline)) read_lradc(int src) +{ + BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src)); + BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src); + while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src))); + return BF_RDn(LRADC_CHn, src, VALUE); +} + +static inline void __attribute__((noreturn)) power_down() +{ + /* power down */ + HW_POWER_RESET = BM_OR2(POWER_RESET, UNLOCK, PWD); + while(1); +} + +/** + * Boot decision functions + */ + +#if defined(CREATIVE_ZENMOZAIC) || defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) +static enum boot_t boot_decision() +{ + setup_lradc(0); // setup LRADC channel 0 to read keys + /* make a decision */ + /* read keys */ + int val = read_lradc(0); + /* if back is pressed, boot to OF + * otherwise boot to RB */ + if(val >= 2650 && val < 2750) // conveniently, all players use the same value + return BOOT_OF; + return BOOT_ROCK; +} +#else +#warning You should define a target specific boot decision function +static int boot_decision() +{ + return BOOT_ROCK; +} +#endif + +static int main(uint32_t rb_addr, uint32_t of_addr) +{ + switch(boot_decision()) + { + case BOOT_ROCK: + return rb_addr; + case BOOT_OF: + /* fix back the loading address + /* NOTE: see mkzenboot for more details */ + *(uint32_t *)0x20 = of_addr; + return 0; + case BOOT_STOP: + default: + power_down(); + } +} + +/** Glue for the linker mostly */ + +extern uint32_t of_vector; +extern uint32_t rb_vector; +extern uint32_t boot_arg; + +void __attribute__((section(".start"))) start() +{ + uint32_t addr = main(rb_vector, of_vector); + ((void (*)(uint32_t))addr)(boot_arg); +} -- cgit v1.2.3