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