]>
Commit | Line | Data |
---|---|---|
bd20f8f4 | 1 | //----------------------------------------------------------------------------- |
2 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, | |
3 | // at your option, any later version. See the LICENSE.txt file for the text of | |
4 | // the license. | |
5 | //----------------------------------------------------------------------------- | |
6 | // Main code for the bootloader | |
7 | //----------------------------------------------------------------------------- | |
8 | ||
15c4dc5a | 9 | #include <proxmark3.h> |
10 | ||
11 | struct common_area common_area __attribute__((section(".commonarea"))); | |
12 | unsigned int start_addr, end_addr, bootrom_unlocked; | |
13 | extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end; | |
14 | ||
15 | static void ConfigClocks(void) | |
16 | { | |
17 | // we are using a 16 MHz crystal as the basis for everything | |
18 | // slow clock runs at 32Khz typical regardless of crystal | |
19 | ||
20 | // enable system clock and USB clock | |
21 | AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK | AT91C_PMC_UDP; | |
22 | ||
23 | // enable the clock to the following peripherals | |
24 | AT91C_BASE_PMC->PMC_PCER = | |
25 | (1<<AT91C_ID_PIOA) | | |
26 | (1<<AT91C_ID_ADC) | | |
27 | (1<<AT91C_ID_SPI) | | |
28 | (1<<AT91C_ID_SSC) | | |
29 | (1<<AT91C_ID_PWMC) | | |
30 | (1<<AT91C_ID_UDP); | |
31 | ||
32 | // worst case scenario, with 16Mhz xtal startup delay is 14.5ms | |
33 | // with a slow clock running at it worst case (max) frequency of 42khz | |
34 | // max startup delay = (14.5ms*42k)/8 = 76 = 0x4C round up to 0x50 | |
35 | ||
36 | // enable main oscillator and set startup delay | |
37 | AT91C_BASE_PMC->PMC_MOR = | |
38 | PMC_MAIN_OSC_ENABLE | | |
39 | PMC_MAIN_OSC_STARTUP_DELAY(0x50); | |
40 | ||
41 | // wait for main oscillator to stabilize | |
42 | while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_STABILIZED) ) | |
43 | ; | |
44 | ||
45 | // minimum PLL clock frequency is 80 MHz in range 00 (96 here so okay) | |
46 | // frequency is crystal * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz | |
47 | AT91C_BASE_PMC->PMC_PLLR = | |
48 | PMC_PLL_DIVISOR(2) | | |
49 | PMC_PLL_COUNT_BEFORE_LOCK(0x50) | | |
50 | PMC_PLL_FREQUENCY_RANGE(0) | | |
51 | PMC_PLL_MULTIPLIER(12) | | |
52 | PMC_PLL_USB_DIVISOR(1); | |
53 | ||
54 | // wait for PLL to lock | |
55 | while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_PLL_LOCK) ) | |
56 | ; | |
57 | ||
58 | // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz | |
59 | // as per datasheet, this register must be programmed in two operations | |
60 | // when changing to PLL, program the prescaler first then the source | |
61 | AT91C_BASE_PMC->PMC_MCKR = PMC_CLK_PRESCALE_DIV_2; | |
62 | ||
63 | // wait for main clock ready signal | |
64 | while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) ) | |
65 | ; | |
66 | ||
67 | // set the source to PLL | |
68 | AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | PMC_CLK_PRESCALE_DIV_2; | |
69 | ||
70 | // wait for main clock ready signal | |
71 | while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) ) | |
72 | ; | |
73 | } | |
74 | ||
75 | static void Fatal(void) | |
76 | { | |
77 | for(;;); | |
78 | } | |
79 | ||
f7e3ed82 | 80 | void UsbPacketReceived(uint8_t *packet, int len) |
15c4dc5a | 81 | { |
82 | int i, dont_ack=0; | |
83 | UsbCommand *c = (UsbCommand *)packet; | |
f7e3ed82 | 84 | volatile uint32_t *p; |
15c4dc5a | 85 | |
86 | if(len != sizeof(*c)) { | |
87 | Fatal(); | |
88 | } | |
89 | ||
90 | switch(c->cmd) { | |
91 | case CMD_DEVICE_INFO: | |
92 | dont_ack = 1; | |
93 | c->cmd = CMD_DEVICE_INFO; | |
94 | c->arg[0] = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | | |
95 | DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; | |
96 | if(common_area.flags.osimage_present) c->arg[0] |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; | |
97 | UsbSendPacket(packet, len); | |
98 | break; | |
99 | ||
100 | case CMD_SETUP_WRITE: | |
101 | /* The temporary write buffer of the embedded flash controller is mapped to the | |
102 | * whole memory region, only the last 8 bits are decoded. | |
103 | */ | |
f7e3ed82 | 104 | p = (volatile uint32_t *)&_flash_start; |
15c4dc5a | 105 | for(i = 0; i < 12; i++) { |
106 | p[i+c->arg[0]] = c->d.asDwords[i]; | |
107 | } | |
108 | break; | |
109 | ||
110 | case CMD_FINISH_WRITE: | |
f7e3ed82 | 111 | p = (volatile uint32_t *)&_flash_start; |
15c4dc5a | 112 | for(i = 0; i < 4; i++) { |
113 | p[i+60] = c->d.asDwords[i]; | |
114 | } | |
115 | ||
116 | /* Check that the address that we are supposed to write to is within our allowed region */ | |
117 | if( ((c->arg[0]+AT91C_IFLASH_PAGE_SIZE-1) >= end_addr) || (c->arg[0] < start_addr) ) { | |
118 | /* Disallow write */ | |
119 | dont_ack = 1; | |
120 | c->cmd = CMD_NACK; | |
121 | UsbSendPacket(packet, len); | |
122 | } else { | |
123 | /* Translate address to flash page and do flash, update here for the 512k part */ | |
124 | AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY | | |
125 | MC_FLASH_COMMAND_PAGEN((c->arg[0]-(int)&_flash_start)/AT91C_IFLASH_PAGE_SIZE) | | |
126 | AT91C_MC_FCMD_START_PROG; | |
127 | } | |
e30c654b | 128 | |
15c4dc5a | 129 | uint32_t sr; |
e30c654b | 130 | |
15c4dc5a | 131 | while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & MC_FLASH_STATUS_READY)) |
132 | ; | |
e30c654b | 133 | if(sr & (MC_FLASH_STATUS_LOCKE | MC_FLASH_STATUS_PROGE)) { |
15c4dc5a | 134 | dont_ack = 1; |
135 | c->cmd = CMD_NACK; | |
136 | UsbSendPacket(packet, len); | |
137 | } | |
138 | break; | |
139 | ||
140 | case CMD_HARDWARE_RESET: | |
141 | USB_D_PLUS_PULLUP_OFF(); | |
142 | AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; | |
143 | break; | |
144 | ||
145 | case CMD_START_FLASH: | |
146 | if(c->arg[2] == START_FLASH_MAGIC) bootrom_unlocked = 1; | |
147 | else bootrom_unlocked = 0; | |
148 | { | |
149 | int prot_start = (int)&_bootrom_start; | |
150 | int prot_end = (int)&_bootrom_end; | |
151 | int allow_start = (int)&_flash_start; | |
152 | int allow_end = (int)&_flash_end; | |
153 | int cmd_start = c->arg[0]; | |
154 | int cmd_end = c->arg[1]; | |
155 | ||
156 | /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected | |
157 | * bootrom area. In any case they must be within the flash area. | |
158 | */ | |
159 | if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) | |
160 | && (cmd_start >= allow_start) && (cmd_end <= allow_end) ) { | |
161 | start_addr = cmd_start; | |
162 | end_addr = cmd_end; | |
163 | } else { | |
164 | start_addr = end_addr = 0; | |
165 | dont_ack = 1; | |
166 | c->cmd = CMD_NACK; | |
167 | UsbSendPacket(packet, len); | |
168 | } | |
169 | } | |
170 | break; | |
171 | ||
172 | default: | |
173 | Fatal(); | |
174 | break; | |
175 | } | |
176 | ||
177 | if(!dont_ack) { | |
178 | c->cmd = CMD_ACK; | |
179 | UsbSendPacket(packet, len); | |
180 | } | |
181 | } | |
182 | ||
183 | static void flash_mode(int externally_entered) | |
184 | { | |
185 | start_addr = 0; | |
186 | end_addr = 0; | |
187 | bootrom_unlocked = 0; | |
188 | ||
189 | UsbStart(); | |
190 | for(;;) { | |
191 | WDT_HIT(); | |
192 | ||
193 | UsbPoll(TRUE); | |
194 | ||
195 | if(!externally_entered && !BUTTON_PRESS()) { | |
196 | /* Perform a reset to leave flash mode */ | |
197 | USB_D_PLUS_PULLUP_OFF(); | |
198 | LED_B_ON(); | |
199 | AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; | |
200 | for(;;); | |
201 | } | |
202 | if(externally_entered && BUTTON_PRESS()) { | |
203 | /* Let the user's button press override the automatic leave */ | |
204 | externally_entered = 0; | |
205 | } | |
206 | } | |
207 | } | |
208 | ||
209 | extern char _osimage_entry; | |
210 | void BootROM(void) | |
211 | { | |
212 | //------------ | |
213 | // First set up all the I/O pins; GPIOs configured directly, other ones | |
214 | // just need to be assigned to the appropriate peripheral. | |
215 | ||
216 | // Kill all the pullups, especially the one on USB D+; leave them for | |
217 | // the unused pins, though. | |
218 | AT91C_BASE_PIOA->PIO_PPUDR = | |
219 | GPIO_USB_PU | | |
220 | GPIO_LED_A | | |
221 | GPIO_LED_B | | |
222 | GPIO_LED_C | | |
223 | GPIO_LED_D | | |
224 | GPIO_FPGA_DIN | | |
225 | GPIO_FPGA_DOUT | | |
226 | GPIO_FPGA_CCLK | | |
227 | GPIO_FPGA_NINIT | | |
228 | GPIO_FPGA_NPROGRAM | | |
229 | GPIO_FPGA_DONE | | |
230 | GPIO_MUXSEL_HIPKD | | |
231 | GPIO_MUXSEL_HIRAW | | |
232 | GPIO_MUXSEL_LOPKD | | |
233 | GPIO_MUXSEL_LORAW | | |
234 | GPIO_RELAY | | |
235 | GPIO_NVDD_ON; | |
236 | // (and add GPIO_FPGA_ON) | |
237 | // These pins are outputs | |
238 | AT91C_BASE_PIOA->PIO_OER = | |
239 | GPIO_LED_A | | |
240 | GPIO_LED_B | | |
241 | GPIO_LED_C | | |
242 | GPIO_LED_D | | |
243 | GPIO_RELAY | | |
244 | GPIO_NVDD_ON; | |
245 | // PIO controls the following pins | |
246 | AT91C_BASE_PIOA->PIO_PER = | |
247 | GPIO_USB_PU | | |
248 | GPIO_LED_A | | |
249 | GPIO_LED_B | | |
250 | GPIO_LED_C | | |
251 | GPIO_LED_D; | |
252 | ||
253 | USB_D_PLUS_PULLUP_OFF(); | |
254 | LED_D_OFF(); | |
255 | LED_C_ON(); | |
256 | LED_B_OFF(); | |
257 | LED_A_OFF(); | |
258 | ||
24b182d0 | 259 | AT91C_BASE_EFC0->EFC_FMR = |
260 | MC_FLASH_MODE_FLASH_WAIT_STATES(1) | | |
261 | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); | |
15c4dc5a | 262 | |
263 | // Initialize all system clocks | |
264 | ConfigClocks(); | |
265 | ||
266 | LED_A_ON(); | |
267 | ||
268 | int common_area_present = 0; | |
269 | switch(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) { | |
270 | case AT91C_RSTC_RSTTYP_WATCHDOG: | |
271 | case AT91C_RSTC_RSTTYP_SOFTWARE: | |
272 | case AT91C_RSTC_RSTTYP_USER: | |
273 | /* In these cases the common_area in RAM should be ok, retain it if it's there */ | |
274 | if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) { | |
275 | common_area_present = 1; | |
276 | } | |
277 | break; | |
278 | default: /* Otherwise, initialize it from scratch */ | |
279 | break; | |
280 | } | |
281 | ||
282 | if(!common_area_present){ | |
283 | /* Common area not ok, initialize it */ | |
284 | int i; for(i=0; i<sizeof(common_area); i++) { /* Makeshift memset, no need to drag util.c into this */ | |
285 | ((char*)&common_area)[i] = 0; | |
286 | } | |
287 | common_area.magic = COMMON_AREA_MAGIC; | |
288 | common_area.version = 1; | |
289 | common_area.flags.bootrom_present = 1; | |
290 | } | |
291 | ||
292 | common_area.flags.bootrom_present = 1; | |
293 | if(common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) { | |
294 | common_area.command = COMMON_AREA_COMMAND_NONE; | |
295 | flash_mode(1); | |
296 | } else if(BUTTON_PRESS()) { | |
297 | flash_mode(0); | |
298 | } else if(*(uint32_t*)&_osimage_entry == 0xffffffffU) { | |
299 | flash_mode(1); | |
300 | } else { | |
301 | // jump to Flash address of the osimage entry point (LSBit set for thumb mode) | |
302 | asm("bx %0\n" : : "r" ( ((int)&_osimage_entry) | 0x1 ) ); | |
303 | } | |
304 | } |