Home | History | Annotate | Download | only in stm32f4xx
      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 
    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 
    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 
    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 
    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 
    275 static uint32_t blExtApiGetVersion(void)
    276 {
    277     return BL_VERSION_CUR;
    278 }
    279 
    280 static void blExtApiReboot(void)
    281 {
    282     SCB->AIRCR = 0x05FA0004;
    283     //we never get here
    284     while(1);
    285 }
    286 
    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  */
    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  */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    601 static bool blExtApiEraseSharedArea(uint32_t key1, uint32_t key2)
    602 {
    603     return blEraseTypedArea(BL_FLASH_SHARED, key1, key2);
    604 }
    605 
    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 
    620 static uint32_t blExtApiVerifyOsUpdate(void)
    621 {
    622     return blVerifyOsUpdate(NULL, NULL);
    623 }
    624 
    625 static void blSupirousIntHandler(void)
    626 {
    627     //BAD!
    628     blExtApiReboot();
    629 }
    630 
    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 
    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 
    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 
    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 
    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 
    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 
    830 static inline bool blUpdateVerify()
    831 {
    832     return blVerifyOsImage(__shared_start, NULL, NULL) == OS_UPDT_SUCCESS;
    833 }
    834 
    835 static void blSpiLoaderDrainRxFifo(struct StmSpi *spi)
    836 {
    837     (void)spi->DR;
    838     while (!(spi->SR & 1));
    839     (void)spi->DR;
    840 }
    841 
    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 
    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 
    859 static bool blSpiLoaderSendSyncOut(struct StmSpi *spi)
    860 {
    861     return blSpiLoaderTxRxByte(spi, BL_SYNC_OUT) == BL_SYNC_IN;
    862 }
    863 
    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 
    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 
   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