diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-10-22 00:48:33 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-10-22 00:48:33 +0200 |
commit | 2e0c558064ad6c92624a0a826721a83321b227af (patch) | |
tree | 6a579d0f24e3b3de023bd3241092f0c89598e1fb /rbutil/mkzenboot/dualboot/dualboot.c | |
parent | 5cfb148ae275993d6b9bc8d59355196c5f4f7dc1 (diff) | |
download | rockbox-2e0c558064ad6c92624a0a826721a83321b227af.tar.gz rockbox-2e0c558064ad6c92624a0a826721a83321b227af.zip |
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
Diffstat (limited to 'rbutil/mkzenboot/dualboot/dualboot.c')
-rw-r--r-- | rbutil/mkzenboot/dualboot/dualboot.c | 134 |
1 files changed, 134 insertions, 0 deletions
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "regs-pinctrl.h" | ||
22 | #include "regs-power.h" | ||
23 | #include "regs-lradc.h" | ||
24 | |||
25 | typedef unsigned long uint32_t; | ||
26 | |||
27 | // target specific boot decision | ||
28 | enum boot_t | ||
29 | { | ||
30 | BOOT_STOP, /* power down */ | ||
31 | BOOT_ROCK, /* boot to Rockbox */ | ||
32 | BOOT_OF, /* boot to OF */ | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * Helper functions | ||
37 | */ | ||
38 | |||
39 | static inline int __attribute__((always_inline)) read_gpio(int bank, int pin) | ||
40 | { | ||
41 | return (HW_PINCTRL_DINn(bank) >> pin) & 1; | ||
42 | } | ||
43 | |||
44 | static inline int __attribute__((always_inline)) read_pswitch(void) | ||
45 | { | ||
46 | #if IMX233_SUBTARGET >= 3700 | ||
47 | return BF_RD(POWER_STS, PSWITCH); | ||
48 | #else | ||
49 | return BF_RD(DIGCTL_STATUS, PSWITCH); | ||
50 | #endif | ||
51 | } | ||
52 | |||
53 | /* only works for channels <=7, always divide by 2, never accumulates */ | ||
54 | static inline void __attribute__((always_inline)) setup_lradc(int src) | ||
55 | { | ||
56 | BF_CLR(LRADC_CTRL0, SFTRST); | ||
57 | BF_CLR(LRADC_CTRL0, CLKGATE); | ||
58 | /* don't bother changing the source, we are early enough at boot so that | ||
59 | * channel x is mapped to source x */ | ||
60 | HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE); | ||
61 | BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src); | ||
62 | } | ||
63 | |||
64 | #define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x) | ||
65 | #define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x)) | ||
66 | |||
67 | static inline int __attribute__((always_inline)) read_lradc(int src) | ||
68 | { | ||
69 | BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src)); | ||
70 | BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src); | ||
71 | while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src))); | ||
72 | return BF_RDn(LRADC_CHn, src, VALUE); | ||
73 | } | ||
74 | |||
75 | static inline void __attribute__((noreturn)) power_down() | ||
76 | { | ||
77 | /* power down */ | ||
78 | HW_POWER_RESET = BM_OR2(POWER_RESET, UNLOCK, PWD); | ||
79 | while(1); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Boot decision functions | ||
84 | */ | ||
85 | |||
86 | #if defined(CREATIVE_ZENMOZAIC) || defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) | ||
87 | static enum boot_t boot_decision() | ||
88 | { | ||
89 | setup_lradc(0); // setup LRADC channel 0 to read keys | ||
90 | /* make a decision */ | ||
91 | /* read keys */ | ||
92 | int val = read_lradc(0); | ||
93 | /* if back is pressed, boot to OF | ||
94 | * otherwise boot to RB */ | ||
95 | if(val >= 2650 && val < 2750) // conveniently, all players use the same value | ||
96 | return BOOT_OF; | ||
97 | return BOOT_ROCK; | ||
98 | } | ||
99 | #else | ||
100 | #warning You should define a target specific boot decision function | ||
101 | static int boot_decision() | ||
102 | { | ||
103 | return BOOT_ROCK; | ||
104 | } | ||
105 | #endif | ||
106 | |||
107 | static int main(uint32_t rb_addr, uint32_t of_addr) | ||
108 | { | ||
109 | switch(boot_decision()) | ||
110 | { | ||
111 | case BOOT_ROCK: | ||
112 | return rb_addr; | ||
113 | case BOOT_OF: | ||
114 | /* fix back the loading address | ||
115 | /* NOTE: see mkzenboot for more details */ | ||
116 | *(uint32_t *)0x20 = of_addr; | ||
117 | return 0; | ||
118 | case BOOT_STOP: | ||
119 | default: | ||
120 | power_down(); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /** Glue for the linker mostly */ | ||
125 | |||
126 | extern uint32_t of_vector; | ||
127 | extern uint32_t rb_vector; | ||
128 | extern uint32_t boot_arg; | ||
129 | |||
130 | void __attribute__((section(".start"))) start() | ||
131 | { | ||
132 | uint32_t addr = main(rb_vector, of_vector); | ||
133 | ((void (*)(uint32_t))addr)(boot_arg); | ||
134 | } | ||