1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <variant/inc/variant.h>
19 
20 #include <plat/inc/cmsis.h>
21 #include <plat/inc/gpio.h>
22 #include <plat/inc/pwr.h>
23 #include <plat/inc/bl.h>
24 
25 #include <nanohub/sha2.h>
26 #include <nanohub/aes.h>
27 #include <nanohub/rsa.h>
28 #include <nanohub/nanohub.h>
29 
30 #include <printf.h>
31 #include <string.h>
32 #include <alloca.h>
33 #include <gpio.h>
34 
35 static uint32_t blVerifyOsImage(const uint8_t *addr, struct OsUpdateHdr **start, uint32_t *size);
36 
37 struct StmCrc
38 {
39     volatile uint32_t DR;
40     volatile uint32_t IDR;
41     volatile uint32_t CR;
42 };
43 
44 struct StmFlash
45 {
46     volatile uint32_t ACR;
47     volatile uint32_t KEYR;
48     volatile uint32_t OPTKEYR;
49     volatile uint32_t SR;
50     volatile uint32_t CR;
51     volatile uint32_t OPTCR;
52 };
53 
54 struct StmRcc {
55     volatile uint32_t CR;
56     volatile uint32_t PLLCFGR;
57     volatile uint32_t CFGR;
58     volatile uint32_t CIR;
59     volatile uint32_t AHB1RSTR;
60     volatile uint32_t AHB2RSTR;
61     volatile uint32_t AHB3RSTR;
62     uint8_t unused0[4];
63     volatile uint32_t APB1RSTR;
64     volatile uint32_t APB2RSTR;
65     uint8_t unused1[8];
66     volatile uint32_t AHB1ENR;
67     volatile uint32_t AHB2ENR;
68     volatile uint32_t AHB3ENR;
69     uint8_t unused2[4];
70     volatile uint32_t APB1ENR;
71     volatile uint32_t APB2ENR;
72     uint8_t unused3[8];
73     volatile uint32_t AHB1LPENR;
74     volatile uint32_t AHB2LPENR;
75     volatile uint32_t AHB3LPENR;
76     uint8_t unused4[4];
77     volatile uint32_t APB1LPENR;
78     volatile uint32_t APB2LPENR;
79     uint8_t unused5[8];
80     volatile uint32_t BDCR;
81     volatile uint32_t CSR;
82     uint8_t unused6[8];
83     volatile uint32_t SSCGR;
84     volatile uint32_t PLLI2SCFGR;
85 };
86 
87 struct StmUdid
88 {
89     volatile uint32_t U_ID[3];
90 };
91 
92 struct StmSpi {
93     volatile uint32_t CR1;
94     volatile uint32_t CR2;
95     volatile uint32_t SR;
96     volatile uint32_t DR;
97     volatile uint32_t CRCPR;
98     volatile uint32_t RXCRCR;
99     volatile uint32_t TXCRCR;
100     volatile uint32_t I2SCFGR;
101     volatile uint32_t I2SPR;
102 };
103 
104 struct StmGpio {
105     volatile uint32_t MODER;
106     volatile uint32_t OTYPER;
107     volatile uint32_t OSPEEDR;
108     volatile uint32_t PUPDR;
109     volatile uint32_t IDR;
110     volatile uint32_t ODR;
111     volatile uint32_t BSRR;
112     volatile uint32_t LCKR;
113     volatile uint32_t AFR[2];
114 };
115 
116 //stm defines
117 #define BL_MAX_FLASH_CODE   1024
118 
119 
120 #define FLASH_ACR_LAT(x)    ((x) & FLASH_ACR_LAT_MASK)
121 #define FLASH_ACR_LAT_MASK  0x0F
122 #define FLASH_ACR_PRFTEN    0x00000100
123 #define FLASH_ACR_ICEN      0x00000200
124 #define FLASH_ACR_DCEN      0x00000400
125 #define FLASH_ACR_ICRST     0x00000800
126 #define FLASH_ACR_DCRST     0x00001000
127 
128 #define FLASH_SR_EOP        0x00000001
129 #define FLASH_SR_OPERR      0x00000002
130 #define FLASH_SR_WRPERR     0x00000010
131 #define FLASH_SR_PGAERR     0x00000020
132 #define FLASH_SR_PGPERR     0x00000040
133 #define FLASH_SR_PGSERR     0x00000080
134 #define FLASH_SR_RDERR      0x00000100
135 #define FLASH_SR_BSY        0x00010000
136 
137 #define FLASH_CR_PG         0x00000001
138 #define FLASH_CR_SER        0x00000002
139 #define FLASH_CR_MER        0x00000004
140 #define FLASH_CR_SNB(x)     (((x) << FLASH_CR_SNB_SHIFT) & FLASH_CR_SNB_MASK)
141 #define FLASH_CR_SNB_MASK   0x00000078
142 #define FLASH_CR_SNB_SHIFT  3
143 #define FLASH_CR_PSIZE(x)   (((x) << FLASH_CR_PSIZE_SHIFT) & FLASH_CR_PSIZE_MASK)
144 #define FLASH_CR_PSIZE_MASK 0x00000300
145 #define FLASH_CR_PSIZE_SHIFT 8
146 #define FLASH_CR_PSIZE_8    0x0
147 #define FLASH_CR_PSIZE_16   0x1
148 #define FLASH_CR_PSIZE_32   0x2
149 #define FLASH_CR_PSIZE_64   0x3
150 #define FLASH_CR_STRT       0x00010000
151 #define FLASH_CR_EOPIE      0x01000000
152 #define FLASH_CR_ERRIE      0x02000000
153 #define FLASH_CR_LOCK       0x80000000
154 
155 //for comms protocol
156 #define BL_SYNC_IN                      0x5A
157 #define BL_ACK                          0x79
158 #define BL_NAK                          0x1F
159 #define BL_SYNC_OUT                     0xA5
160 
161 #define BL_CMD_GET                      0x00
162 #define BL_CMD_READ_MEM                 0x11
163 #define BL_CMD_WRITE_MEM                0x31
164 #define BL_CMD_ERASE                    0x44
165 #define BL_CMD_GET_SIZES                0xEE /* our own command. reports: {u32 osSz, u32 sharedSz, u32 eeSz} all in big endian */
166 #define BL_CMD_UPDATE_FINISHED          0xEF /* our own command. attempts to verify the update -> ACK/NAK. MUST be called after upload to mark it as completed */
167 
168 #define BL_SHARED_AREA_FAKE_ERASE_BLK   0xFFF0
169 #define BL_SHARED_AREA_FAKE_ADDR        0x50000000
170 
171 
172 typedef void (*FlashEraseF)(volatile uint32_t *, uint32_t, volatile uint32_t *);
173 typedef void (*FlashWriteF)(volatile uint8_t *, uint8_t, volatile uint32_t *);
174 
175 //linker provides these
176 extern uint32_t __pubkeys_start[];
177 extern uint32_t __pubkeys_end[];
178 extern uint8_t __stack_top[];
179 extern uint8_t __ram_start[];
180 extern uint8_t __ram_end[];
181 extern uint8_t __eedata_start[];
182 extern uint8_t __eedata_end[];
183 extern uint8_t __code_start[];
184 extern uint8_t __code_end[];
185 extern uint8_t __shared_start[];
186 extern uint8_t __shared_end[];
187 extern void __VECTORS();
188 
189 //make GCC happy
190 void __blEntry(void);
191 
192 enum BlFlashType
193 {
194     BL_FLASH_BL,
195     BL_FLASH_EEDATA,
196     BL_FLASH_KERNEL,
197     BL_FLASH_SHARED
198 };
199 
200 static const struct blFlashTable   // For erase code, we need to know which page a given memory address is in
201 {
202     uint8_t *address;
203     uint32_t length;
204     uint32_t type;
205 } mBlFlashTable[] =
206 #ifndef BL_FLASH_TABLE
207 {
208     { (uint8_t *)(&BL),                      0x04000, BL_FLASH_BL     },
209     { (uint8_t *)(__eedata_start),           0x04000, BL_FLASH_EEDATA },
210     { (uint8_t *)(__eedata_start + 0x04000), 0x04000, BL_FLASH_EEDATA },
211     { (uint8_t *)(__code_start),             0x04000, BL_FLASH_KERNEL },
212     { (uint8_t *)(__code_start + 0x04000),   0x10000, BL_FLASH_KERNEL },
213     { (uint8_t *)(__shared_start),           0x20000, BL_FLASH_SHARED },
214     { (uint8_t *)(__shared_start + 0x20000), 0x20000, BL_FLASH_SHARED },
215     { (uint8_t *)(__shared_start + 0x40000), 0x20000, BL_FLASH_SHARED },
216 };
217 #else
218 BL_FLASH_TABLE;
219 #endif
220 
221 static const char mOsUpdateMagic[] = OS_UPDT_MAGIC;
222 
223 //BL stack
224 uint64_t __attribute__ ((section (".stack"))) _STACK[BL_STACK_SIZE / sizeof(uint64_t)];
225 
226 
227 #ifdef DEBUG_UART_PIN
228 
blLogPutcharF(void * userData,char ch)229 static bool blLogPutcharF(void *userData, char ch)
230 {
231     if (ch == '\n')
232         gpioBitbangedUartOut('\r');
233 
234     gpioBitbangedUartOut(ch);
235 
236     return true;
237 }
238 
blLog(const char * str,...)239 void blLog(const char *str, ...)
240 {
241     va_list vl;
242 
243     va_start(vl, str);
244     cvprintf(blLogPutcharF, NULL, str, vl);
245     va_end(vl);
246 }
247 
248 #else
249 
250 #define blLog(...)
251 
252 #endif
253 
blDisableInts(void)254 static inline uint32_t blDisableInts(void)
255 {
256     uint32_t state;
257 
258     asm volatile (
259         "mrs %0, PRIMASK    \n"
260         "cpsid i            \n"
261         :"=r"(state)
262     );
263 
264     return state;
265 }
266 
blRestoreInts(uint32_t state)267 static inline void blRestoreInts(uint32_t state)
268 {
269     asm volatile(
270         "msr PRIMASK, %0   \n"
271         ::"r"((uint32_t)state)
272     );
273 }
274 
blExtApiGetVersion(void)275 static uint32_t blExtApiGetVersion(void)
276 {
277     return BL_VERSION_CUR;
278 }
279 
blExtApiReboot(void)280 static void blExtApiReboot(void)
281 {
282     SCB->AIRCR = 0x05FA0004;
283     //we never get here
284     while(1);
285 }
286 
blExtApiGetSnum(uint32_t * snum,uint32_t length)287 static void blExtApiGetSnum(uint32_t *snum, uint32_t length)
288 {
289     struct StmUdid *reg = (struct StmUdid *)UDID_BASE;
290     uint32_t i;
291 
292     if (length > 3)
293         length = 3;
294 
295     for (i = 0; i < length; i++)
296         snum[i] = reg->U_ID[i];
297 }
298 
299 /*
300  * Return the address of the erase code and the length of the code
301  *
302  * This code needs to run out of ram and not flash since accessing flash
303  * while erasing is undefined (best case the processor stalls, worst case
304  * it starts executing garbage)
305  *
306  * This function is used to get a pointer to the actual code that does the
307  * erase and polls for completion (so we can copy it to ram) as well as the
308  * length of the code (so we know how much space to allocate for it)
309  *
310  * void FlashEraseF(volatile uint32_t *addr, uint32_t value, volatile uint32_t *status)
311  * {
312  *     *addr = value;
313  *     while (*status & FLASH_SR_BSY) ;
314  * }
315  */
blGetFlashEraseCode(uint16_t ** addr,uint32_t * size)316 static void __attribute__((naked)) blGetFlashEraseCode(uint16_t **addr, uint32_t *size)
317 {
318     asm volatile (
319         "  push {lr}          \n"
320         "  bl   9f            \n"
321         "  str  r1, [r0, #0]  \n" // *addr = value
322         "1:                   \n"
323         "  ldr  r3, [r2, #0]  \n" // r3 = *status
324         "  lsls r3, #15       \n" // r3 <<= 15
325         "  bmi  1b            \n" // if (r3 < 0) goto 1
326         "  bx   lr            \n" // return
327         "9:                   \n"
328         "  bic  lr, #0x1      \n"
329         "  adr  r3, 9b        \n"
330         "  sub  r3, lr        \n"
331         "  str  lr, [r0]      \n"
332         "  str  r3, [r1]      \n"
333         "  pop {pc}           \n"
334     );
335 }
336 
337 /*
338  * Return the address of the write code and the length of the code
339  *
340  * This code needs to run out of ram and not flash since accessing flash
341  * while writing to flash is undefined (best case the processor stalls, worst
342  * case it starts executing garbage)
343  *
344  * This function is used to get a pointer to the actual code that does the
345  * write and polls for completion (so we can copy it to ram) as well as the
346  * length of the code (so we know how much space to allocate for it)
347  *
348  * void FlashWriteF(volatile uint8_t *addr, uint8_t value, volatile uint32_t *status)
349  * {
350  *     *addr = value;
351  *     while (*status & FLASH_SR_BSY) ;
352  * }
353  */
blGetFlashWriteCode(uint16_t ** addr,uint32_t * size)354 static void __attribute__((naked)) blGetFlashWriteCode(uint16_t **addr, uint32_t *size)
355 {
356     asm volatile (
357         "  push {lr}          \n"
358         "  bl   9f            \n"
359         "  strb r1, [r0, #0]  \n" // *addr = value
360         "1:                   \n"
361         "  ldr  r3, [r2, #0]  \n" // r3 = *status
362         "  lsls r3, #15       \n" // r3 <<= 15
363         "  bmi  1b            \n" // if (r3 < 0) goto 1
364         "  bx   lr            \n" // return
365         "9:                   \n"
366         "  bic  lr, #0x1      \n"
367         "  adr  r3, 9b        \n"
368         "  sub  r3, lr        \n"
369         "  str  lr, [r0]      \n"
370         "  str  r3, [r1]      \n"
371         "  pop {pc}           \n"
372     );
373 }
374 
blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask)375 static void blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask)
376 {
377     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
378     uint16_t *code_src, *code;
379     uint32_t i, code_length;
380     FlashEraseF func;
381 
382     blGetFlashEraseCode(&code_src, &code_length);
383 
384     if (code_length < BL_MAX_FLASH_CODE) {
385         code = (uint16_t *)(((uint32_t)alloca(code_length + 1) + 1) & ~0x1);
386         func = (FlashEraseF)((uint8_t *)code+1);
387 
388         for (i = 0; i < code_length / sizeof(uint16_t); i++)
389             code[i] = code_src[i];
390 
391         for (i = 0; i < sector_cnt; i++) {
392             if (erase_mask[i]) {
393                 flash->CR = (flash->CR & ~(FLASH_CR_SNB_MASK)) |
394                     FLASH_CR_SNB(i) | FLASH_CR_SER;
395                 func(&flash->CR, flash->CR | FLASH_CR_STRT, &flash->SR);
396                 flash->CR &= ~(FLASH_CR_SNB_MASK | FLASH_CR_SER);
397             }
398         }
399     }
400 }
401 
blWriteBytes(uint8_t * dst,const uint8_t * src,uint32_t length)402 static void blWriteBytes(uint8_t *dst, const uint8_t *src, uint32_t length)
403 {
404     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
405     uint16_t *code_src, *code;
406     uint32_t i, code_length;
407     FlashWriteF func;
408 
409     blGetFlashWriteCode(&code_src, &code_length);
410 
411     if (code_length < BL_MAX_FLASH_CODE) {
412         code = (uint16_t *)(((uint32_t)alloca(code_length+1) + 1) & ~0x1);
413         func = (FlashWriteF)((uint8_t *)code+1);
414 
415         for (i = 0; i < code_length / sizeof(uint16_t); i++)
416             code[i] = code_src[i];
417 
418         flash->CR |= FLASH_CR_PG;
419 
420         for (i = 0; i < length; i++) {
421             if (dst[i] != src[i])
422                 func(&dst[i], src[i], &flash->SR);
423         }
424 
425         flash->CR &= ~FLASH_CR_PG;
426     }
427 }
428 
blProgramFlash(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)429 static bool blProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
430 {
431     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
432     const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable);
433     uint32_t acr_cache, cr_cache, offset, i, j = 0, int_state = 0;
434     uint8_t *ptr;
435 
436     if (((length == 0)) ||
437         ((0xFFFFFFFF - (uint32_t)dst) < (length - 1)) ||
438         ((dst < mBlFlashTable[0].address)) ||
439         ((dst + length) > (mBlFlashTable[sector_cnt-1].address +
440                            mBlFlashTable[sector_cnt-1].length))) {
441         return false;
442     }
443 
444     // compute which flash block we are starting from
445     for (i = 0; i < sector_cnt; i++) {
446         if (dst >= mBlFlashTable[i].address &&
447             dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) {
448             break;
449         }
450     }
451 
452     // now loop through all the flash blocks and see if we have to do any
453     // 0 -> 1 transitions of a bit. If so, return false
454     // 1 -> 0 transitions of a bit do not require an erase
455     offset = (uint32_t)(dst - mBlFlashTable[i].address);
456     ptr = mBlFlashTable[i].address;
457     while (j < length && i < sector_cnt) {
458         if (offset == mBlFlashTable[i].length) {
459             i++;
460             offset = 0;
461             ptr = mBlFlashTable[i].address;
462         }
463 
464         if ((ptr[offset] & src[j]) != src[j]) {
465             return false;
466         } else {
467             j++;
468             offset++;
469         }
470     }
471 
472     // disable interrupts
473     // otherwise an interrupt during flash write will stall the processor
474     // until the write completes
475     int_state = blDisableInts();
476 
477     // wait for flash to not be busy (should never be set at this point)
478     while (flash->SR & FLASH_SR_BSY);
479 
480     cr_cache = flash->CR;
481 
482     if (flash->CR & FLASH_CR_LOCK) {
483         // unlock flash
484         flash->KEYR = key1;
485         flash->KEYR = key2;
486     }
487 
488     if (flash->CR & FLASH_CR_LOCK) {
489         // unlock failed, restore interrupts
490         blRestoreInts(int_state);
491 
492         return false;
493     }
494 
495     flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
496 
497     acr_cache = flash->ACR;
498 
499     // disable and flush data and instruction caches
500     flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
501     flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
502 
503     blWriteBytes(dst, src, length);
504 
505     flash->ACR = acr_cache;
506     flash->CR = cr_cache;
507 
508     blRestoreInts(int_state);
509 
510     return !memcmp(dst, src, length);
511 }
512 
blProgramTypedArea(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t type,uint32_t key1,uint32_t key2)513 static bool blProgramTypedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t type, uint32_t key1, uint32_t key2)
514 {
515     const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable);
516     uint32_t i;
517 
518     for (i = 0; i < sector_cnt; i++) {
519 
520         if ((dst >= mBlFlashTable[i].address &&
521              dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) ||
522             (dst < mBlFlashTable[i].address &&
523              (dst + length > mBlFlashTable[i].address))) {
524             if (mBlFlashTable[i].type != type)
525                 return false;
526         }
527     }
528 
529     return blProgramFlash(dst, src, length, key1, key2);
530 }
531 
blExtApiProgramSharedArea(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)532 static bool blExtApiProgramSharedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
533 {
534     return blProgramTypedArea(dst, src, length, BL_FLASH_SHARED, key1, key2);
535 }
536 
blExtApiProgramEe(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)537 static bool blExtApiProgramEe(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
538 {
539     return blProgramTypedArea(dst, src, length, BL_FLASH_EEDATA, key1, key2);
540 }
541 
blEraseTypedArea(uint32_t type,uint32_t key1,uint32_t key2)542 static bool blEraseTypedArea(uint32_t type, uint32_t key1, uint32_t key2)
543 {
544     struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
545     const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable);
546     uint32_t i, acr_cache, cr_cache, erase_cnt = 0, int_state = 0;
547     uint8_t erase_mask[sector_cnt];
548 
549     for (i = 0; i < sector_cnt; i++) {
550         if (mBlFlashTable[i].type == type) {
551             erase_mask[i] = 1;
552             erase_cnt++;
553         } else {
554             erase_mask[i] = 0;
555         }
556     }
557 
558     // disable interrupts
559     // otherwise an interrupt during flash write/erase will stall the processor
560     // until the write/erase completes
561     int_state = blDisableInts();
562 
563     // wait for flash to not be busy (should never be set at this point)
564     while (flash->SR & FLASH_SR_BSY);
565 
566     cr_cache = flash->CR;
567 
568     if (flash->CR & FLASH_CR_LOCK) {
569         // unlock flash
570         flash->KEYR = key1;
571         flash->KEYR = key2;
572     }
573 
574     if (flash->CR & FLASH_CR_LOCK) {
575         // unlock failed, restore interrupts
576         blRestoreInts(int_state);
577 
578         return false;
579     }
580 
581     flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
582 
583     acr_cache = flash->ACR;
584 
585     // disable and flush data and instruction caches
586     flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
587     flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
588 
589     if (erase_cnt)
590         blEraseSectors(sector_cnt, erase_mask);
591 
592     flash->ACR = acr_cache;
593     flash->CR = cr_cache;
594 
595     // restore interrupts
596     blRestoreInts(int_state);
597 
598     return true; //we assume erase worked
599 }
600 
blExtApiEraseSharedArea(uint32_t key1,uint32_t key2)601 static bool blExtApiEraseSharedArea(uint32_t key1, uint32_t key2)
602 {
603     return blEraseTypedArea(BL_FLASH_SHARED, key1, key2);
604 }
605 
blVerifyOsUpdate(struct OsUpdateHdr ** start,uint32_t * size)606 static uint32_t blVerifyOsUpdate(struct OsUpdateHdr **start, uint32_t *size)
607 {
608     uint32_t ret;
609     int i;
610 
611     for (i = 0; i < BL_SCAN_OFFSET; i += 4) {
612         ret = blVerifyOsImage(__shared_start + i, start, size);
613         if (ret != OS_UPDT_HDR_CHECK_FAILED)
614             break;
615     }
616 
617     return ret;
618 }
619 
blExtApiVerifyOsUpdate(void)620 static uint32_t blExtApiVerifyOsUpdate(void)
621 {
622     return blVerifyOsUpdate(NULL, NULL);
623 }
624 
blSupirousIntHandler(void)625 static void blSupirousIntHandler(void)
626 {
627     //BAD!
628     blExtApiReboot();
629 }
630 
blExtApiGetRsaKeyInfo(uint32_t * numKeys)631 static const uint32_t *blExtApiGetRsaKeyInfo(uint32_t *numKeys)
632 {
633     uint32_t numWords = __pubkeys_end - __pubkeys_start;
634 
635     if (numWords % RSA_WORDS) // something is wrong
636         return NULL;
637 
638     *numKeys = numWords / RSA_WORDS;
639     return __pubkeys_start;
640 }
641 
blExtApiSigPaddingVerify(const uint32_t * rsaResult)642 static const uint32_t* blExtApiSigPaddingVerify(const uint32_t *rsaResult)
643 {
644     uint32_t i;
645 
646     //all but first and last word of padding MUST have no zero bytes
647     for (i = SHA2_HASH_WORDS + 1; i < RSA_WORDS - 1; i++) {
648         if (!(uint8_t)(rsaResult[i] >>  0))
649             return NULL;
650         if (!(uint8_t)(rsaResult[i] >>  8))
651             return NULL;
652         if (!(uint8_t)(rsaResult[i] >> 16))
653             return NULL;
654         if (!(uint8_t)(rsaResult[i] >> 24))
655             return NULL;
656     }
657 
658     //first padding word must have all nonzero bytes except low byte
659     if ((rsaResult[SHA2_HASH_WORDS] & 0xff) || !(rsaResult[SHA2_HASH_WORDS] & 0xff00) || !(rsaResult[SHA2_HASH_WORDS] & 0xff0000) || !(rsaResult[SHA2_HASH_WORDS] & 0xff000000))
660         return NULL;
661 
662     //last padding word must have 0x0002 in top 16 bits and nonzero random bytes in lower bytes
663     if ((rsaResult[RSA_WORDS - 1] >> 16) != 2)
664         return NULL;
665     if (!(rsaResult[RSA_WORDS - 1] & 0xff00) || !(rsaResult[RSA_WORDS - 1] & 0xff))
666         return NULL;
667 
668     return rsaResult;
669 }
670 
671 const struct BlVecTable __attribute__((section(".blvec"))) __BL_VECTORS =
672 {
673     /* cortex */
674     .blStackTop = (uint32_t)&__stack_top,
675     .blEntry = &__blEntry,
676     .blNmiHandler = &blSupirousIntHandler,
677     .blMmuFaultHandler = &blSupirousIntHandler,
678     .blBusFaultHandler = &blSupirousIntHandler,
679     .blUsageFaultHandler = &blSupirousIntHandler,
680 
681     /* api */
682     .blGetVersion = &blExtApiGetVersion,
683     .blReboot = &blExtApiReboot,
684     .blGetSnum = &blExtApiGetSnum,
685     .blProgramShared = &blExtApiProgramSharedArea,
686     .blEraseShared = &blExtApiEraseSharedArea,
687     .blProgramEe = &blExtApiProgramEe,
688     .blGetPubKeysInfo = &blExtApiGetRsaKeyInfo,
689     .blRsaPubOpIterative = &rsaPubOpIterative,
690     .blSha2init = &sha2init,
691     .blSha2processBytes = &sha2processBytes,
692     .blSha2finish = &sha2finish,
693     .blAesInitForEncr = &aesInitForEncr,
694     .blAesInitForDecr = &aesInitForDecr,
695     .blAesEncr = &aesEncr,
696     .blAesDecr = &aesDecr,
697     .blAesCbcInitForEncr = &aesCbcInitForEncr,
698     .blAesCbcInitForDecr = &aesCbcInitForDecr,
699     .blAesCbcEncr = &aesCbcEncr,
700     .blAesCbcDecr = &aesCbcDecr,
701     .blSigPaddingVerify = &blExtApiSigPaddingVerify,
702     .blVerifyOsUpdate = &blExtApiVerifyOsUpdate,
703 };
704 
blApplyVerifiedUpdate(const struct OsUpdateHdr * os)705 static void blApplyVerifiedUpdate(const struct OsUpdateHdr *os) //only called if an update has been found to exist and be valid, signed, etc!
706 {
707     //copy shared to code, and if successful, erase shared area
708     if (blEraseTypedArea(BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2))
709         if (blProgramTypedArea(__code_start, (const uint8_t*)(os + 1), os->size, BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2))
710             (void)blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2);
711 }
712 
blWriteMark(struct OsUpdateHdr * hdr,uint32_t mark)713 static void blWriteMark(struct OsUpdateHdr *hdr, uint32_t mark)
714 {
715     uint8_t dstVal = mark;
716 
717     (void)blExtApiProgramSharedArea(&hdr->marker, &dstVal, sizeof(hdr->marker), BL_FLASH_KEY1, BL_FLASH_KEY2);
718 }
719 
blUpdateMark(uint32_t old,uint32_t new)720 static void blUpdateMark(uint32_t old, uint32_t new)
721 {
722     struct OsUpdateHdr *hdr = (struct OsUpdateHdr *)__shared_start;
723 
724     if (hdr->marker != old)
725         return;
726 
727     blWriteMark(hdr, new);
728 }
729 
blVerifyOsImage(const uint8_t * addr,struct OsUpdateHdr ** start,uint32_t * size)730 static uint32_t blVerifyOsImage(const uint8_t *addr, struct OsUpdateHdr **start, uint32_t *size)
731 {
732     const uint32_t *rsaKey, *osSigHash, *osSigPubkey, *ourHash, *rsaResult, *expectedHash = NULL;
733     struct OsUpdateHdr *hdr = (struct OsUpdateHdr*)addr;
734     struct OsUpdateHdr cpy;
735     uint32_t i, numRsaKeys = 0, rsaStateVar1, rsaStateVar2, rsaStep = 0;
736     const uint8_t *updateBinaryData;
737     bool isValid = false;
738     struct Sha2state sha;
739     struct RsaState rsa;
740     uint32_t ret = OS_UPDT_HDR_CHECK_FAILED;
741     const uint32_t overhead = sizeof(*hdr) + 2 * RSA_WORDS;
742 
743     // header does not fit or is not aligned
744     if (addr < __shared_start || addr > (__shared_end - overhead) || ((uintptr_t)addr & 3))
745         return OS_UPDT_HDR_CHECK_FAILED;
746 
747     // image does not fit
748     if (hdr->size > (__shared_end - addr - overhead))
749         return OS_UPDT_HDR_CHECK_FAILED;
750 
751     // OS magic does not match
752     if (memcmp(hdr->magic, mOsUpdateMagic, sizeof(hdr->magic)) != 0)
753         return OS_UPDT_HDR_CHECK_FAILED;
754 
755     // we don't allow shortcuts on success path, but we want to fail quickly
756     if (hdr->marker == OS_UPDT_MARKER_INVALID)
757         return OS_UPDT_HDR_MARKER_INVALID;
758 
759     // download did not finish
760     if (hdr->marker == OS_UPDT_MARKER_INPROGRESS)
761         return OS_UPDT_HDR_MARKER_INVALID;
762 
763     //get pointers
764     updateBinaryData = (const uint8_t*)(hdr + 1);
765     osSigHash = (const uint32_t*)(updateBinaryData + hdr->size);
766     osSigPubkey = osSigHash + RSA_WORDS;
767 
768     //make sure the pub key is known
769     for (i = 0, rsaKey = blExtApiGetRsaKeyInfo(&numRsaKeys); i < numRsaKeys; i++, rsaKey += RSA_WORDS) {
770         if (memcmp(rsaKey, osSigPubkey, RSA_BYTES) == 0)
771             break;
772     }
773 
774     if (i == numRsaKeys) {
775         ret = OS_UPDT_UNKNOWN_PUBKEY;
776         //signed with an unknown key -> fail
777         goto fail;
778     }
779 
780     //decode sig using pubkey
781     do {
782         rsaResult = rsaPubOpIterative(&rsa, osSigHash, osSigPubkey, &rsaStateVar1, &rsaStateVar2, &rsaStep);
783     } while (rsaStep);
784 
785     if (!rsaResult) {
786         //decode fails -> invalid sig
787         ret = OS_UPDT_INVALID_SIGNATURE;
788         goto fail;
789     }
790 
791     //verify padding
792     expectedHash = blExtApiSigPaddingVerify(rsaResult);
793 
794     if (!expectedHash) {
795         //padding check fails -> invalid sig
796         ret = OS_UPDT_INVALID_SIGNATURE_HASH;
797         goto fail;
798     }
799 
800     //hash the update
801     sha2init(&sha);
802 
803     memcpy(&cpy, hdr, sizeof(cpy));
804     cpy.marker = OS_UPDT_MARKER_INPROGRESS;
805     sha2processBytes(&sha, &cpy, sizeof(cpy));
806     sha2processBytes(&sha, (uint8_t*)(hdr + 1), hdr->size);
807     ourHash = sha2finish(&sha);
808 
809     //verify hash match
810     if (memcmp(expectedHash, ourHash, SHA2_HASH_SIZE) != 0) {
811         //hash does not match -> data tampered with
812         ret = OS_UPDT_INVALID_SIGNATURE_HASH; // same error; do not disclose nature of hash problem
813         goto fail;
814     }
815 
816     //it is valid
817     isValid = true;
818     ret = OS_UPDT_SUCCESS;
819     if (start)
820         *start = hdr;
821     if (size)
822         *size = hdr->size;
823 
824 fail:
825     //mark it appropriately
826     blWriteMark(hdr, isValid ? OS_UPDT_MARKER_VERIFIED : OS_UPDT_MARKER_INVALID);
827     return ret;
828 }
829 
blUpdateVerify()830 static inline bool blUpdateVerify()
831 {
832     return blVerifyOsImage(__shared_start, NULL, NULL) == OS_UPDT_SUCCESS;
833 }
834 
blSpiLoaderDrainRxFifo(struct StmSpi * spi)835 static void blSpiLoaderDrainRxFifo(struct StmSpi *spi)
836 {
837     (void)spi->DR;
838     while (!(spi->SR & 1));
839     (void)spi->DR;
840 }
841 
blSpiLoaderTxRxByte(struct StmSpi * spi,uint32_t val)842 static uint8_t blSpiLoaderTxRxByte(struct StmSpi *spi, uint32_t val)
843 {
844     while (!(spi->SR & 2));
845     spi->DR = val;
846     while (!(spi->SR & 1));
847     return spi->DR;
848 }
849 
blSpiLoaderTxBytes(struct StmSpi * spi,const void * data,uint32_t len)850 static void blSpiLoaderTxBytes(struct StmSpi *spi, const void *data, uint32_t len)
851 {
852     const uint8_t *buf = (const uint8_t*)data;
853 
854     blSpiLoaderTxRxByte(spi, len - 1);
855     while (len--)
856         blSpiLoaderTxRxByte(spi, *buf++);
857 }
858 
blSpiLoaderSendSyncOut(struct StmSpi * spi)859 static bool blSpiLoaderSendSyncOut(struct StmSpi *spi)
860 {
861     return blSpiLoaderTxRxByte(spi, BL_SYNC_OUT) == BL_SYNC_IN;
862 }
863 
blSpiLoaderSendAck(struct StmSpi * spi,bool ack)864 static bool blSpiLoaderSendAck(struct StmSpi *spi, bool ack)
865 {
866     blSpiLoaderTxRxByte(spi, 0);
867     blSpiLoaderTxRxByte(spi, ack ? BL_ACK : BL_NAK);
868     return blSpiLoaderTxRxByte(spi, 0) == BL_ACK;
869 }
870 
blSpiLoader(bool force)871 static void blSpiLoader(bool force)
872 {
873     const uint32_t intInPin = SH_INT_WAKEUP - GPIO_PA(0);
874     struct StmGpio *gpioa = (struct StmGpio*)GPIOA_BASE;
875     struct StmSpi *spi = (struct StmSpi*)SPI1_BASE;
876     struct StmRcc *rcc = (struct StmRcc*)RCC_BASE;
877     uint32_t oldApb2State, oldAhb1State, nRetries;
878     bool seenErase = false;
879     uint32_t nextAddr = 0;
880     uint32_t expectedSize = 0;
881 
882     if (SH_INT_WAKEUP < GPIO_PA(0) || SH_INT_WAKEUP > GPIO_PA(15)) {
883 
884         //link time assert :)
885         extern void ThisIsAnError_BlIntPinNotInGpioA(void);
886         ThisIsAnError_BlIntPinNotInGpioA();
887     }
888 
889     //SPI & GPIOA on
890     oldApb2State = rcc->APB2ENR;
891     oldAhb1State = rcc->AHB1ENR;
892     rcc->APB2ENR |= PERIPH_APB2_SPI1;
893     rcc->AHB1ENR |= PERIPH_AHB1_GPIOA;
894 
895     //reset units
896     rcc->APB2RSTR |= PERIPH_APB2_SPI1;
897     rcc->AHB1RSTR |= PERIPH_AHB1_GPIOA;
898     rcc->APB2RSTR &=~ PERIPH_APB2_SPI1;
899     rcc->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
900 
901     //configure GPIOA for SPI A4..A7 for SPI use (function 5), int pin as not func, high speed, no pullups, not open drain, proper directions
902     gpioa->AFR[0] = (gpioa->AFR[0] & 0x0000ffff & ~(0x0f << (intInPin * 4))) | 0x55550000;
903     gpioa->OSPEEDR |= 0x0000ff00 | (3 << (intInPin * 2));
904     gpioa->PUPDR &=~ (0x0000ff00 | (3 << (intInPin * 2)));
905     gpioa->OTYPER &=~ (0x00f0 | (1 << intInPin));
906     gpioa->MODER = (gpioa->MODER & 0xffff00ff & ~(0x03 << (intInPin * 2))) | 0x0000aa00;
907 
908     //if int pin is not low, do not bother any further
909     if (!(gpioa->IDR & (1 << intInPin)) || force) {
910 
911         //config SPI
912         spi->CR1 = 0x00000040; //spi is on, configured same as bootloader would
913         spi->CR2 = 0x00000000; //spi is on, configured same as bootloader would
914 
915         //wait for sync
916         for (nRetries = 10000; nRetries; nRetries--) {
917             if (spi->SR & 1) {
918                 if (spi->DR == BL_SYNC_IN)
919                     break;
920                 (void)spi->SR; //re-read to clear overlfow condition (if any)
921             }
922         }
923 
924         //if we saw a sync, do the bootloader thing
925         if (nRetries) {
926             static const uint8_t supportedCmds[] = {BL_CMD_GET, BL_CMD_READ_MEM, BL_CMD_WRITE_MEM, BL_CMD_ERASE, BL_CMD_GET_SIZES, BL_CMD_UPDATE_FINISHED};
927             uint32_t allSizes[] = {__builtin_bswap32(__code_end - __code_start), __builtin_bswap32(__shared_end - __shared_start), __builtin_bswap32(__eedata_end - __eedata_start)};
928             bool ack = true;  //we ack the sync
929 
930             ack = blSpiLoaderSendSyncOut(spi);
931 
932             //loop forever listening to commands
933             while (1) {
934                 uint32_t sync, cmd, cmdNot, addr = 0, len, checksum = 0, i;
935                 uint8_t data[256];
936 
937                 //send ack or NAK for last thing
938                 if (!blSpiLoaderSendAck(spi, ack))
939                     goto out;
940 
941                 while ((sync = blSpiLoaderTxRxByte(spi, 0)) != BL_SYNC_IN);
942                 cmd = blSpiLoaderTxRxByte(spi, 0);
943                 cmdNot = blSpiLoaderTxRxByte(spi, BL_ACK);
944 
945                 ack = false;
946                 if (sync == BL_SYNC_IN && (cmd ^ cmdNot) == 0xff) switch (cmd) {
947                 case BL_CMD_GET:
948 
949                     //ACK the command
950                     (void)blSpiLoaderSendAck(spi, true);
951 
952                     blSpiLoaderTxBytes(spi, supportedCmds, sizeof(supportedCmds));
953                     ack = true;
954                     break;
955 
956                 case BL_CMD_READ_MEM:
957                     if (!seenErase)  //no reading till we erase the shared area (this way we do not leak encrypted apps' plaintexts)
958                         break;
959 
960                     //ACK the command
961                     (void)blSpiLoaderSendAck(spi, true);
962 
963                     //get address
964                     for (i = 0; i < 4; i++) {
965                         uint32_t byte = blSpiLoaderTxRxByte(spi, 0);
966                         checksum ^= byte;
967                         addr = (addr << 8) + byte;
968                     }
969 
970                     //reject addresses outside of our fake area or on invalid checksum
971                     if (blSpiLoaderTxRxByte(spi, 0) != checksum || addr < BL_SHARED_AREA_FAKE_ADDR || addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start)
972                        break;
973 
974                     //ack the address
975                     (void)blSpiLoaderSendAck(spi, true);
976 
977                     //get the length
978                     len = blSpiLoaderTxRxByte(spi, 0);
979 
980                     //reject invalid checksum
981                     if (blSpiLoaderTxRxByte(spi, 0) != (uint8_t)~len || addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start)
982                        break;
983 
984                     len++;
985 
986                     //reject reads past the end of the shared area
987                     if (addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start)
988                        break;
989 
990                     //ack the length
991                     (void)blSpiLoaderSendAck(spi, true);
992 
993                     //read the data & send it
994                     blSpiLoaderTxBytes(spi, __shared_start + addr - BL_SHARED_AREA_FAKE_ADDR, len);
995                     ack = true;
996                     break;
997 
998                 case BL_CMD_WRITE_MEM:
999                     if (!seenErase)  //no writing till we erase the shared area (this way we do not purposefully modify encrypted apps' plaintexts in a nefarious fashion)
1000                         break;
1001 
1002                     //ACK the command
1003                     (void)blSpiLoaderSendAck(spi, true);
1004 
1005                     //get address
1006                     for (i = 0; i < 4; i++) {
1007                         uint32_t byte = blSpiLoaderTxRxByte(spi, 0);
1008                         checksum ^= byte;
1009                         addr = (addr << 8) + byte;
1010                     }
1011 
1012                     //reject addresses outside of our fake area or on invalid checksum
1013                     if (blSpiLoaderTxRxByte(spi, 0) != checksum ||
1014                         addr < BL_SHARED_AREA_FAKE_ADDR ||
1015                         addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start)
1016                         break;
1017 
1018                     addr -= BL_SHARED_AREA_FAKE_ADDR;
1019                     if (addr != nextAddr)
1020                         break;
1021 
1022                     //ack the address
1023                     (void)blSpiLoaderSendAck(spi, true);
1024 
1025                     //get the length
1026                     checksum = len = blSpiLoaderTxRxByte(spi, 0);
1027                     len++;
1028 
1029                     //get bytes
1030                     for (i = 0; i < len; i++) {
1031                         uint32_t byte = blSpiLoaderTxRxByte(spi, 0);
1032                         checksum ^= byte;
1033                         data[i] = byte;
1034                     }
1035 
1036                     //reject writes that takes out outside fo shared area or invalid checksums
1037                     if (blSpiLoaderTxRxByte(spi, 0) != checksum || addr + len > __shared_end - __shared_start)
1038                        break;
1039 
1040                     // OBSOLETE: superseded by sequential contiguous write requirement
1041                     //if (addr && addr < sizeof(struct OsUpdateHdr))
1042                     //    break;
1043 
1044                     //a write starting at zero must be big enough to contain a full OS update header
1045                     if (!addr) {
1046                         const struct OsUpdateHdr *hdr = (const struct OsUpdateHdr*)data;
1047 
1048                         //verify it is at least as big as the header
1049                         if (len < sizeof(struct OsUpdateHdr))
1050                             break;
1051 
1052                         //check for magic
1053                         for (i = 0; i < sizeof(hdr->magic) && hdr->magic[i] == mOsUpdateMagic[i]; i++);
1054 
1055                         //verify magic check passed & marker is properly set to inprogress
1056                         if (i != sizeof(hdr->magic) || hdr->marker != OS_UPDT_MARKER_INPROGRESS)
1057                             break;
1058                         expectedSize = sizeof(*hdr) + hdr->size + 2 * RSA_BYTES;
1059                     }
1060                     if (addr + len > expectedSize)
1061                         break;
1062 
1063                     //do it
1064                     ack = blExtApiProgramSharedArea(__shared_start + addr, data, len, BL_FLASH_KEY1, BL_FLASH_KEY2);
1065                     blSpiLoaderDrainRxFifo(spi);
1066                     nextAddr += len;
1067                     break;
1068 
1069                 case BL_CMD_ERASE:
1070 
1071                     //ACK the command
1072                     (void)blSpiLoaderSendAck(spi, true);
1073 
1074                     //get address
1075                     for (i = 0; i < 2; i++) {
1076                         uint32_t byte = blSpiLoaderTxRxByte(spi, 0);
1077                         checksum ^= byte;
1078                         addr = (addr << 8) + byte;
1079                     }
1080 
1081                     //reject addresses that are not our magic address or on invalid checksum
1082                     if (blSpiLoaderTxRxByte(spi, 0) != checksum || addr != BL_SHARED_AREA_FAKE_ERASE_BLK)
1083                         break;
1084 
1085                     //do it
1086                     ack = blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2);
1087                     if (ack) {
1088                         seenErase = true;
1089                         nextAddr = 0;
1090                         expectedSize = 0;
1091                     }
1092                     blSpiLoaderDrainRxFifo(spi);
1093                     break;
1094 
1095                 case BL_CMD_GET_SIZES:
1096 
1097                     //ACK the command
1098                     (void)blSpiLoaderSendAck(spi, true);
1099 
1100                     blSpiLoaderTxBytes(spi, allSizes, sizeof(allSizes));
1101                     break;
1102 
1103                 case BL_CMD_UPDATE_FINISHED:
1104                     blUpdateMark(OS_UPDT_MARKER_INPROGRESS, OS_UPDT_MARKER_DOWNLOADED);
1105                     ack = blUpdateVerify();
1106                     break;
1107                 }
1108             }
1109         }
1110     }
1111 
1112 out:
1113     //reset units & return APB2 & AHB1 to initial state
1114     rcc->APB2RSTR |= PERIPH_APB2_SPI1;
1115     rcc->AHB1RSTR |= PERIPH_AHB1_GPIOA;
1116     rcc->APB2RSTR &=~ PERIPH_APB2_SPI1;
1117     rcc->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
1118     rcc->APB2ENR = oldApb2State;
1119     rcc->AHB1ENR = oldAhb1State;
1120 }
1121 
__blEntry(void)1122 void __blEntry(void)
1123 {
1124     extern char __bss_end[], __bss_start[], __data_end[], __data_start[], __data_data[];
1125     uint32_t appBase = ((uint32_t)&__code_start) & ~1;
1126     bool forceLoad = false;
1127 
1128     //make sure we're the vector table and no ints happen (BL does not use them)
1129     blDisableInts();
1130     SCB->VTOR = (uint32_t)&BL;
1131 
1132     //init things a little for the higher levels
1133     memset(__bss_start, 0, __bss_end - __bss_start);
1134     memcpy(__data_start, __data_data, __data_end - __data_start);
1135 
1136     //say hello
1137     blLog("NanohubOS bootloader up @ %p\n", &__blEntry);
1138 
1139     //enter SPI loader if requested
1140     do {
1141         uint32_t res;
1142         struct OsUpdateHdr *os;
1143 
1144         blSpiLoader(forceLoad);
1145         res = blVerifyOsUpdate(&os, NULL);
1146         if (res == OS_UPDT_SUCCESS)
1147             blApplyVerifiedUpdate(os);
1148         else if (res != OS_UPDT_HDR_CHECK_FAILED)
1149             blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2);
1150 
1151         forceLoad = true;
1152     } while (*(volatile uint32_t*)appBase == 0xFFFFFFFF);
1153 
1154     //call main app with ints off
1155     blDisableInts();
1156     SCB->VTOR = appBase;
1157     asm volatile(
1158         "LDR SP, [%0, #0]    \n"
1159         "LDR PC, [%0, #4]    \n"
1160         :
1161         :"r"(appBase)
1162         :"memory", "cc"
1163     );
1164 
1165     //we should never return here
1166     while(1);
1167 }
1168