1 #include <alloca.h>
2 #include <stdbool.h>
3 #include <string.h>
4 
5 #include <variant/variant.h>
6 
7 #include <plat/pwr.h>
8 #include <plat/gpio.h>
9 #include <plat/cmsis.h>
10 
11 #include <bl.h>
12 #include <gpio.h>
13 
14 struct StmUdid
15 {
16     volatile uint32_t U_ID[3];
17 };
18 
19 struct StmSpi {
20     volatile uint32_t CR1;
21     volatile uint32_t CR2;
22     volatile uint32_t SR;
23     volatile uint32_t DR;
24     volatile uint32_t CRCPR;
25     volatile uint32_t RXCRCR;
26     volatile uint32_t TXCRCR;
27     volatile uint32_t I2SCFGR;
28     volatile uint32_t I2SPR;
29 };
30 
31 struct StmGpio {
32     volatile uint32_t MODER;
33     volatile uint32_t OTYPER;
34     volatile uint32_t OSPEEDR;
35     volatile uint32_t PUPDR;
36     volatile uint32_t IDR;
37     volatile uint32_t ODR;
38     volatile uint32_t BSRR;
39     volatile uint32_t LCKR;
40     volatile uint32_t AFR[2];
41 };
42 
43 struct StmFlash
44 {
45     volatile uint32_t ACR;
46     volatile uint32_t KEYR;
47     volatile uint32_t OPTKEYR;
48     volatile uint32_t SR;
49     volatile uint32_t CR;
50     volatile uint32_t OPTCR;
51 };
52 
53 struct StmCrc
54 {
55     volatile uint32_t DR;
56     volatile uint32_t IDR;
57     volatile uint32_t CR;
58 };
59 
60 struct StmRcc {
61     volatile uint32_t CR;
62     volatile uint32_t PLLCFGR;
63     volatile uint32_t CFGR;
64     volatile uint32_t CIR;
65     volatile uint32_t AHB1RSTR;
66     volatile uint32_t AHB2RSTR;
67     volatile uint32_t AHB3RSTR;
68     uint8_t unused0[4];
69     volatile uint32_t APB1RSTR;
70     volatile uint32_t APB2RSTR;
71     uint8_t unused1[8];
72     volatile uint32_t AHB1ENR;
73     volatile uint32_t AHB2ENR;
74     volatile uint32_t AHB3ENR;
75     uint8_t unused2[4];
76     volatile uint32_t APB1ENR;
77     volatile uint32_t APB2ENR;
78     uint8_t unused3[8];
79     volatile uint32_t AHB1LPENR;
80     volatile uint32_t AHB2LPENR;
81     volatile uint32_t AHB3LPENR;
82     uint8_t unused4[4];
83     volatile uint32_t APB1LPENR;
84     volatile uint32_t APB2LPENR;
85     uint8_t unused5[8];
86     volatile uint32_t BDCR;
87     volatile uint32_t CSR;
88     uint8_t unused6[8];
89     volatile uint32_t SSCGR;
90     volatile uint32_t PLLI2SCFGR;
91 };
92 
93 typedef void (*FlashEraseF)(volatile uint32_t *, uint32_t, volatile uint32_t *);
94 typedef void (*FlashWriteF)(volatile uint8_t *, uint8_t, volatile uint32_t *);
95 
96 static struct StmSpi *SPI;
97 static struct StmRcc *RCC;
98 static struct Gpio *wakeupGpio;
99 static uint32_t mOldApb2State;
100 static uint32_t mOldAhb1State;
101 
102 #define FLASH_ACR_LAT(x)    ((x) & FLASH_ACR_LAT_MASK)
103 #define FLASH_ACR_LAT_MASK  0x0F
104 #define FLASH_ACR_PRFTEN    0x00000100
105 #define FLASH_ACR_ICEN      0x00000200
106 #define FLASH_ACR_DCEN      0x00000400
107 #define FLASH_ACR_ICRST     0x00000800
108 #define FLASH_ACR_DCRST     0x00001000
109 
110 #define FLASH_SR_EOP        0x00000001
111 #define FLASH_SR_OPERR      0x00000002
112 #define FLASH_SR_WRPERR     0x00000010
113 #define FLASH_SR_PGAERR     0x00000020
114 #define FLASH_SR_PGPERR     0x00000040
115 #define FLASH_SR_PGSERR     0x00000080
116 #define FLASH_SR_RDERR      0x00000100
117 #define FLASH_SR_BSY        0x00010000
118 
119 #define FLASH_CR_PG         0x00000001
120 #define FLASH_CR_SER        0x00000002
121 #define FLASH_CR_MER        0x00000004
122 #define FLASH_CR_SNB(x)     (((x) << FLASH_CR_SNB_SHIFT) & FLASH_CR_SNB_MASK)
123 #define FLASH_CR_SNB_MASK   0x00000078
124 #define FLASH_CR_SNB_SHIFT  3
125 #define FLASH_CR_PSIZE(x)   (((x) << FLASH_CR_PSIZE_SHIFT) & FLASH_CR_PSIZE_MASK)
126 #define FLASH_CR_PSIZE_MASK 0x00000300
127 #define FLASH_CR_PSIZE_SHIFT 8
128 #define FLASH_CR_PSIZE_8    0x0
129 #define FLASH_CR_PSIZE_16   0x1
130 #define FLASH_CR_PSIZE_32   0x2
131 #define FLASH_CR_PSIZE_64   0x3
132 #define FLASH_CR_STRT       0x00010000
133 #define FLASH_CR_EOPIE      0x01000000
134 #define FLASH_CR_ERRIE      0x02000000
135 #define FLASH_CR_LOCK       0x80000000
136 
137 //stm defines
138 #define BL_MAX_FLASH_CODE   1024
139 
140 /*
141  * Return the address of the erase code and the length of the code
142  *
143  * This code needs to run out of ram and not flash since accessing flash
144  * while erasing is undefined (best case the processor stalls, worst case
145  * it starts executing garbage)
146  *
147  * This function is used to get a pointer to the actual code that does the
148  * erase and polls for completion (so we can copy it to ram) as well as the
149  * length of the code (so we know how much space to allocate for it)
150  *
151  * void FlashEraseF(volatile uint32_t *addr, uint32_t value, volatile uint32_t *status)
152  * {
153  *     *addr = value;
154  *     while (*status & FLASH_SR_BSY) ;
155  * }
156  */
blGetFlashEraseCode(uint16_t ** addr,uint32_t * size)157 static void __attribute__((naked)) blGetFlashEraseCode(uint16_t **addr, uint32_t *size)
158 {
159     asm volatile (
160         "  push {lr}          \n"
161         "  bl   9f            \n"
162         "  str  r1, [r0, #0]  \n" // *addr = value
163         "1:                   \n"
164         "  ldr  r3, [r2, #0]  \n" // r3 = *status
165         "  lsls r3, #15       \n" // r3 <<= 15
166         "  bmi  1b            \n" // if (r3 < 0) goto 1
167         "  bx   lr            \n" // return
168         "9:                   \n"
169         "  bic  lr, #0x1      \n"
170         "  adr  r3, 9b        \n"
171         "  sub  r3, lr        \n"
172         "  str  lr, [r0]      \n"
173         "  str  r3, [r1]      \n"
174         "  pop {pc}           \n"
175     );
176 }
177 
_blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask)178 static void _blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask)
179 {
180     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
181     uint16_t *code_src, *code;
182     uint32_t i, code_length;
183     FlashEraseF func;
184 
185     blGetFlashEraseCode(&code_src, &code_length);
186 
187     if (code_length < BL_MAX_FLASH_CODE) {
188         code = (uint16_t *)(((uint32_t)alloca(code_length + 1) + 1) & ~0x1);
189         func = (FlashEraseF)((uint8_t *)code+1);
190 
191         for (i = 0; i < code_length / sizeof(uint16_t); i++)
192             code[i] = code_src[i];
193 
194         for (i = 0; i < sector_cnt; i++) {
195             if (erase_mask[i]) {
196                 flash->CR = (flash->CR & ~(FLASH_CR_SNB_MASK)) |
197                     FLASH_CR_SNB(i) | FLASH_CR_SER;
198                 func(&flash->CR, flash->CR | FLASH_CR_STRT, &flash->SR);
199                 flash->CR &= ~(FLASH_CR_SNB_MASK | FLASH_CR_SER);
200             }
201         }
202     }
203 }
204 
blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask,uint32_t key1,uint32_t key2)205 bool blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask, uint32_t key1, uint32_t key2)
206 {
207     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
208     uint32_t acr_cache, cr_cache;
209     // disable interrupts
210     // otherwise an interrupt during flash write/erase will stall the processor
211     // until the write/erase completes
212     uint32_t int_state = blDisableInts();
213 
214     // wait for flash to not be busy (should never be set at this point)
215     while (flash->SR & FLASH_SR_BSY);
216 
217     cr_cache = flash->CR;
218 
219     if (flash->CR & FLASH_CR_LOCK) {
220         // unlock flash
221         flash->KEYR = key1;
222         flash->KEYR = key2;
223     }
224 
225     if (!(flash->CR & FLASH_CR_LOCK)) {
226         flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
227         acr_cache = flash->ACR;
228 
229         // disable and flush data and instruction caches
230         flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
231         flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
232 
233         _blEraseSectors(sector_cnt, erase_mask);
234 
235         flash->ACR = acr_cache;
236         flash->CR = cr_cache;
237 
238         // restore interrupts
239         blRestoreInts(int_state);
240         return true;
241     }
242     return false;
243 }
244 
245 /*
246  * Return the address of the write code and the length of the code
247  *
248  * This code needs to run out of ram and not flash since accessing flash
249  * while writing to flash is undefined (best case the processor stalls, worst
250  * case it starts executing garbage)
251  *
252  * This function is used to get a pointer to the actual code that does the
253  * write and polls for completion (so we can copy it to ram) as well as the
254  * length of the code (so we know how much space to allocate for it)
255  *
256  * void FlashWriteF(volatile uint8_t *addr, uint8_t value, volatile uint32_t *status)
257  * {
258  *     *addr = value;
259  *     while (*status & FLASH_SR_BSY) ;
260  * }
261  */
blGetFlashWriteCode(uint16_t ** addr,uint32_t * size)262 static void __attribute__((naked)) blGetFlashWriteCode(uint16_t **addr, uint32_t *size)
263 {
264     asm volatile (
265         "  push {lr}          \n"
266         "  bl   9f            \n"
267         "  strb r1, [r0, #0]  \n" // *addr = value
268         "1:                   \n"
269         "  ldr  r3, [r2, #0]  \n" // r3 = *status
270         "  lsls r3, #15       \n" // r3 <<= 15
271         "  bmi  1b            \n" // if (r3 < 0) goto 1
272         "  bx   lr            \n" // return
273         "9:                   \n"
274         "  bic  lr, #0x1      \n"
275         "  adr  r3, 9b        \n"
276         "  sub  r3, lr        \n"
277         "  str  lr, [r0]      \n"
278         "  str  r3, [r1]      \n"
279         "  pop {pc}           \n"
280     );
281 }
282 
blWriteBytes(uint8_t * dst,const uint8_t * src,uint32_t length)283 static void blWriteBytes(uint8_t *dst, const uint8_t *src, uint32_t length)
284 {
285     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
286     uint16_t *code_src, *code;
287     uint32_t i, code_length;
288     FlashWriteF func;
289 
290     blGetFlashWriteCode(&code_src, &code_length);
291 
292     if (code_length < BL_MAX_FLASH_CODE) {
293         code = (uint16_t *)(((uint32_t)alloca(code_length+1) + 1) & ~0x1);
294         func = (FlashWriteF)((uint8_t *)code+1);
295 
296         for (i = 0; i < code_length / sizeof(uint16_t); i++)
297             code[i] = code_src[i];
298 
299         flash->CR |= FLASH_CR_PG;
300 
301         for (i = 0; i < length; i++) {
302             if (dst[i] != src[i])
303                 func(&dst[i], src[i], &flash->SR);
304         }
305 
306         flash->CR &= ~FLASH_CR_PG;
307     }
308 }
309 
blPlatProgramFlash(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)310 bool blPlatProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
311 {
312     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
313     uint32_t acr_cache, cr_cache;
314     // disable interrupts
315     // otherwise an interrupt during flash write will stall the processor
316     // until the write completes
317     uint32_t int_state = blDisableInts();
318 
319     // wait for flash to not be busy (should never be set at this point)
320     while (flash->SR & FLASH_SR_BSY);
321 
322     cr_cache = flash->CR;
323 
324     if (flash->CR & FLASH_CR_LOCK) {
325         // unlock flash
326         flash->KEYR = key1;
327         flash->KEYR = key2;
328     }
329 
330     if (flash->CR & FLASH_CR_LOCK) {
331         // unlock failed, restore interrupts
332         blRestoreInts(int_state);
333 
334         return false;
335     }
336 
337     flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
338 
339     acr_cache = flash->ACR;
340 
341     // disable and flush data and instruction caches
342     flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
343     flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
344 
345     blWriteBytes(dst, src, length);
346 
347     flash->ACR = acr_cache;
348     flash->CR = cr_cache;
349 
350     blRestoreInts(int_state);
351     return true;
352 }
353 
blDisableInts(void)354 uint32_t blDisableInts(void)
355 {
356     uint32_t state;
357 
358     asm volatile (
359         "mrs %0, PRIMASK    \n"
360         "cpsid i            \n"
361         :"=r"(state)
362     );
363 
364     return state;
365 }
366 
blRestoreInts(uint32_t state)367 void blRestoreInts(uint32_t state)
368 {
369     asm volatile(
370         "msr PRIMASK, %0   \n"
371         ::"r"((uint32_t)state)
372     );
373 }
374 
blReboot(void)375 void blReboot(void)
376 {
377     SCB->AIRCR = 0x05FA0004;
378     //we never get here
379     while(1);
380 }
381 
blResetRxData()382 void blResetRxData()
383 {
384     (void)SPI->DR;
385     while (!(SPI->SR & 1));
386     (void)SPI->DR;
387 }
388 
blSpiTxRxByte(uint32_t val)389 uint8_t blSpiTxRxByte(uint32_t val)
390 {
391     while (!(SPI->SR & 2));
392     SPI->DR = val;
393     while (!(SPI->SR & 1));
394     return SPI->DR;
395 }
396 
blGetSnum(uint32_t * snum,uint32_t length)397 uint32_t blGetSnum(uint32_t *snum, uint32_t length)
398 {
399     struct StmUdid *reg = (struct StmUdid *)UDID_BASE;
400     uint32_t i;
401 
402     if (length > 3)
403         length = 3;
404 
405     for (i = 0; i < length; i++)
406         snum[i] = reg->U_ID[i];
407 
408     return (length << 2);
409 }
410 
blSetup()411 void blSetup()
412 {
413     SPI = (struct StmSpi*)SPI1_BASE;
414     RCC = (struct StmRcc*)RCC_BASE;
415     struct Gpio *gpio;
416     int i;
417 
418     //SPI1 & GPIOA on
419     mOldApb2State = RCC->APB2ENR;
420     mOldAhb1State = RCC->AHB1ENR;
421     RCC->APB2ENR |= PERIPH_APB2_SPI1;
422     RCC->AHB1ENR |= PERIPH_AHB1_GPIOA;
423 
424     //reset units
425     RCC->APB2RSTR |= PERIPH_APB2_SPI1;
426     RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
427     RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
428     RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
429 
430     //configure GPIOA for SPI A4..A7 for AF_SPI1 use (function 5), int pin as not func, high speed, no pullups, not open drain, proper directions
431     for (i=4; i<=7; i++) {
432         gpio = gpioRequest(GPIO_PA(i));
433         gpioConfigAlt(gpio, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_OUT_PUSH_PULL, GPIO_AF_SPI1);
434         gpioRelease(gpio);
435     }
436 
437     wakeupGpio = gpioRequest(SH_INT_WAKEUP);
438     gpioConfigInput(wakeupGpio, GPIO_SPEED_HIGH, GPIO_PULL_NONE);
439 }
440 
blCleanup()441 void blCleanup()
442 {
443     gpioRelease(wakeupGpio);
444     //reset units & return APB2 & AHB1 to initial state
445     RCC->APB2RSTR |= PERIPH_APB2_SPI1;
446     RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
447     RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
448     RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
449     RCC->APB2ENR = mOldApb2State;
450     RCC->AHB1ENR = mOldAhb1State;
451 }
452 
blHostActive()453 bool blHostActive()
454 {
455     return !gpioGet(wakeupGpio);
456 }
457 
blConfigIo()458 void blConfigIo()
459 {
460     //config SPI
461     SPI->CR1 = 0x00000040; //spi is on, configured same as bootloader would
462     SPI->CR2 = 0x00000000; //spi is on, configured same as bootloader would
463 }
464 
blSyncWait(uint32_t syncCode)465 bool blSyncWait(uint32_t syncCode)
466 {
467     uint32_t nRetries;
468     //wait for sync
469     for (nRetries = 10000; nRetries; nRetries--) {
470         if (SPI->SR & 1) {
471             if (SPI->DR == syncCode)
472                 break;
473             (void)SPI->SR; //re-read to clear overlfow condition (if any)
474         }
475     }
476     return nRetries > 0;
477 }
478 
479 void __attribute__((noreturn)) __blEntry(void);
__blEntry(void)480 void __attribute__((noreturn)) __blEntry(void)
481 {
482     extern char __code_start[], __bss_end[], __bss_start[], __data_end[], __data_start[], __data_data[];
483     uint32_t appBase = ((uint32_t)&__code_start) & ~1;
484 
485     //make sure we're the vector table and no ints happen (BL does not use them)
486     blDisableInts();
487     SCB->VTOR = (uint32_t)&BL;
488 
489     //init things a little for the higher levels
490     memset(__bss_start, 0, __bss_end - __bss_start);
491     memcpy(__data_start, __data_data, __data_end - __data_start);
492 
493     blMain(appBase);
494 
495     //call OS with ints off
496     blDisableInts();
497     SCB->VTOR = appBase;
498     asm volatile(
499         "LDR SP, [%0, #0]    \n"
500         "LDR PC, [%0, #4]    \n"
501         :
502         :"r"(appBase)
503         :"memory", "cc"
504     );
505 
506     //we should never return here
507     while(1);
508 }
509 
blSpuriousIntHandler(void)510 static void blSpuriousIntHandler(void)
511 {
512     //BAD!
513     blReboot();
514 }
515 
516 extern uint8_t __stack_top[];
517 uint64_t __attribute__ ((section (".stack"))) _STACK[BL_STACK_SIZE / sizeof(uint64_t)];
518 
519 const struct BlVecTable __attribute__((section(".blvec"))) __BL_VEC =
520 {
521     .blStackTop             = (uint32_t)&__stack_top,
522     .blEntry                = &__blEntry,
523     .blNmiHandler           = &blSpuriousIntHandler,
524     .blHardFaultHandler     = &blSpuriousIntHandler,
525     .blMmuFaultHandler      = &blSpuriousIntHandler,
526     .blBusFaultHandler      = &blSpuriousIntHandler,
527     .blUsageFaultHandler    = &blSpuriousIntHandler,
528 };
529