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 #include <variant/variant.h> 18 19 #include <bl.h> 20 21 #include <plat/cmsis.h> 22 #include <plat/gpio.h> 23 24 #include <nanohub/sha2.h> 25 #include <nanohub/aes.h> 26 #include <nanohub/rsa.h> 27 #include <nanohub/nanohub.h> 28 29 #include <printf.h> 30 #include <string.h> 31 32 static uint32_t blVerifyOsImage(const uint8_t *addr, struct OsUpdateHdr **start, uint32_t *size); 33 34 35 //for comms protocol 36 #define BL_SYNC_IN 0x5A 37 #define BL_ACK 0x79 38 #define BL_NAK 0x1F 39 #define BL_SYNC_OUT 0xA5 40 41 #define BL_CMD_GET 0x00 42 #define BL_CMD_READ_MEM 0x11 43 #define BL_CMD_WRITE_MEM 0x31 44 #define BL_CMD_ERASE 0x44 45 #define BL_CMD_GET_SIZES 0xEE /* our own command. reports: {u32 osSz, u32 sharedSz, u32 eeSz} all in big endian */ 46 #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 */ 47 48 #define BL_ERROR 0xDEADBEAF /* returned in place of command in case of exchange errors */ 49 50 51 #define BL_SHARED_AREA_FAKE_ERASE_BLK 0xFFF0 52 #define BL_SHARED_AREA_FAKE_ADDR 0x50000000 53 54 55 //linker provides these 56 extern uint32_t __pubkeys_start[]; 57 extern uint32_t __pubkeys_end[]; 58 extern uint8_t __eedata_start[]; 59 extern uint8_t __eedata_end[]; 60 extern uint8_t __code_start[]; 61 extern uint8_t __code_end[]; 62 extern uint8_t __shared_start[]; 63 extern uint8_t __shared_end[]; 64 65 enum BlFlashType 66 { 67 BL_FLASH_BL, 68 BL_FLASH_EEDATA, 69 BL_FLASH_KERNEL, 70 BL_FLASH_SHARED 71 }; 72 73 static const struct blFlashTable // For erase code, we need to know which page a given memory address is in 74 { 75 uint8_t *address; 76 uint32_t length; 77 uint32_t type; 78 } mBlFlashTable[] = 79 #ifndef BL_FLASH_TABLE 80 { 81 { (uint8_t *)(&BL), 0x04000, BL_FLASH_BL }, 82 { (uint8_t *)(__eedata_start), 0x04000, BL_FLASH_EEDATA }, 83 { (uint8_t *)(__eedata_start + 0x04000), 0x04000, BL_FLASH_EEDATA }, 84 { (uint8_t *)(__code_start), 0x04000, BL_FLASH_KERNEL }, 85 { (uint8_t *)(__code_start + 0x04000), 0x10000, BL_FLASH_KERNEL }, 86 { (uint8_t *)(__code_start + 0x14000), 0x20000, BL_FLASH_KERNEL }, 87 { (uint8_t *)(__shared_start), 0x20000, BL_FLASH_SHARED }, 88 { (uint8_t *)(__shared_start + 0x20000), 0x20000, BL_FLASH_SHARED }, 89 }; 90 #else 91 BL_FLASH_TABLE; 92 #endif 93 94 static const char mOsUpdateMagic[] = OS_UPDT_MAGIC; 95 96 #ifdef DEBUG_UART_PIN 97 98 static bool blLogPutcharF(void *userData, char ch) 99 { 100 if (ch == '\n') 101 gpioBitbangedUartOut('\r'); 102 103 gpioBitbangedUartOut(ch); 104 105 return true; 106 } 107 108 void blLog(const char *str, ...) 109 { 110 va_list vl; 111 112 va_start(vl, str); 113 cvprintf(blLogPutcharF, 0, NULL, str, vl); 114 va_end(vl); 115 } 116 117 #else 118 119 #define blLog(...) 120 121 #endif 122 123 static uint32_t blExtApiGetVersion(void) 124 { 125 return BL_VERSION_CUR; 126 } 127 128 static bool blProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2) 129 { 130 const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable); 131 uint32_t offset, i, j = 0; 132 uint8_t *ptr; 133 134 if (((length == 0)) || 135 ((0xFFFFFFFF - (uint32_t)dst) < (length - 1)) || 136 ((dst < mBlFlashTable[0].address)) || 137 ((dst + length) > (mBlFlashTable[sector_cnt-1].address + 138 mBlFlashTable[sector_cnt-1].length))) { 139 return false; 140 } 141 142 // compute which flash block we are starting from 143 for (i = 0; i < sector_cnt; i++) { 144 if (dst >= mBlFlashTable[i].address && 145 dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) { 146 break; 147 } 148 } 149 150 // now loop through all the flash blocks and see if we have to do any 151 // 0 -> 1 transitions of a bit. If so, return false 152 // 1 -> 0 transitions of a bit do not require an erase 153 offset = (uint32_t)(dst - mBlFlashTable[i].address); 154 ptr = mBlFlashTable[i].address; 155 while (j < length && i < sector_cnt) { 156 if (offset == mBlFlashTable[i].length) { 157 i++; 158 offset = 0; 159 ptr = mBlFlashTable[i].address; 160 } 161 162 if ((ptr[offset] & src[j]) != src[j]) { 163 return false; 164 } else { 165 j++; 166 offset++; 167 } 168 } 169 170 if (!blPlatProgramFlash(dst, src, length, key1, key2)) 171 return false; 172 173 return !memcmp(dst, src, length); 174 } 175 176 static void blExtApiGetSnum(uint32_t *snum, uint32_t length) 177 { 178 blGetSnum(snum, length); 179 } 180 181 static bool blProgramTypedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t type, uint32_t key1, uint32_t key2) 182 { 183 const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable); 184 uint32_t i; 185 186 for (i = 0; i < sector_cnt; i++) { 187 188 if ((dst >= mBlFlashTable[i].address && 189 dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) || 190 (dst < mBlFlashTable[i].address && 191 (dst + length > mBlFlashTable[i].address))) { 192 if (mBlFlashTable[i].type != type) 193 return false; 194 } 195 } 196 197 return blProgramFlash(dst, src, length, key1, key2); 198 } 199 200 static bool blExtApiProgramSharedArea(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2) 201 { 202 return blProgramTypedArea(dst, src, length, BL_FLASH_SHARED, key1, key2); 203 } 204 205 static bool blExtApiProgramEe(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2) 206 { 207 return blProgramTypedArea(dst, src, length, BL_FLASH_EEDATA, key1, key2); 208 } 209 210 static bool blEraseTypedArea(uint32_t type, uint32_t key1, uint32_t key2) 211 { 212 const uint32_t sector_cnt = sizeof(mBlFlashTable) / sizeof(struct blFlashTable); 213 uint32_t i, erase_cnt = 0; 214 uint8_t erase_mask[sector_cnt]; 215 216 for (i = 0; i < sector_cnt; i++) { 217 if (mBlFlashTable[i].type == type) { 218 erase_mask[i] = 1; 219 erase_cnt++; 220 } else { 221 erase_mask[i] = 0; 222 } 223 } 224 225 if (erase_cnt) 226 blEraseSectors(sector_cnt, erase_mask, key1, key2); 227 228 return true; //we assume erase worked 229 } 230 231 static bool blExtApiEraseSharedArea(uint32_t key1, uint32_t key2) 232 { 233 return blEraseTypedArea(BL_FLASH_SHARED, key1, key2); 234 } 235 236 static uint32_t blVerifyOsUpdate(struct OsUpdateHdr **start, uint32_t *size) 237 { 238 uint32_t ret; 239 int i; 240 241 for (i = 0; i < BL_SCAN_OFFSET; i += 4) { 242 ret = blVerifyOsImage(__shared_start + i, start, size); 243 if (ret != OS_UPDT_HDR_CHECK_FAILED) 244 break; 245 } 246 247 return ret; 248 } 249 250 static uint32_t blExtApiVerifyOsUpdate(void) 251 { 252 return blVerifyOsUpdate(NULL, NULL); 253 } 254 255 static void blExtApiReboot(void) 256 { 257 blReboot(); 258 } 259 260 static const uint32_t *blExtApiGetRsaKeyInfo(uint32_t *numKeys) 261 { 262 uint32_t numWords = __pubkeys_end - __pubkeys_start; 263 264 if (numWords % RSA_WORDS) // something is wrong 265 return NULL; 266 267 *numKeys = numWords / RSA_WORDS; 268 return __pubkeys_start; 269 } 270 271 static const uint32_t* blExtApiSigPaddingVerify(const uint32_t *rsaResult) 272 { 273 uint32_t i; 274 275 //all but first and last word of padding MUST have no zero bytes 276 for (i = SHA2_HASH_WORDS + 1; i < RSA_WORDS - 1; i++) { 277 if (!(uint8_t)(rsaResult[i] >> 0)) 278 return NULL; 279 if (!(uint8_t)(rsaResult[i] >> 8)) 280 return NULL; 281 if (!(uint8_t)(rsaResult[i] >> 16)) 282 return NULL; 283 if (!(uint8_t)(rsaResult[i] >> 24)) 284 return NULL; 285 } 286 287 //first padding word must have all nonzero bytes except low byte 288 if ((rsaResult[SHA2_HASH_WORDS] & 0xff) || !(rsaResult[SHA2_HASH_WORDS] & 0xff00) || !(rsaResult[SHA2_HASH_WORDS] & 0xff0000) || !(rsaResult[SHA2_HASH_WORDS] & 0xff000000)) 289 return NULL; 290 291 //last padding word must have 0x0002 in top 16 bits and nonzero random bytes in lower bytes 292 if ((rsaResult[RSA_WORDS - 1] >> 16) != 2) 293 return NULL; 294 if (!(rsaResult[RSA_WORDS - 1] & 0xff00) || !(rsaResult[RSA_WORDS - 1] & 0xff)) 295 return NULL; 296 297 return rsaResult; 298 } 299 300 static void blApplyVerifiedUpdate(const struct OsUpdateHdr *os) //only called if an update has been found to exist and be valid, signed, etc! 301 { 302 //copy shared to code, and if successful, erase shared area 303 if (blEraseTypedArea(BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2)) 304 if (blProgramTypedArea(__code_start, (const uint8_t*)(os + 1), os->size, BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2)) 305 (void)blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2); 306 } 307 308 static void blWriteMark(struct OsUpdateHdr *hdr, uint32_t mark) 309 { 310 uint8_t dstVal = mark; 311 312 (void)blExtApiProgramSharedArea(&hdr->marker, &dstVal, sizeof(hdr->marker), BL_FLASH_KEY1, BL_FLASH_KEY2); 313 } 314 315 static void blUpdateMark(uint32_t old, uint32_t new) 316 { 317 struct OsUpdateHdr *hdr = (struct OsUpdateHdr *)__shared_start; 318 319 if (hdr->marker != old) 320 return; 321 322 blWriteMark(hdr, new); 323 } 324 325 static uint32_t blVerifyOsImage(const uint8_t *addr, struct OsUpdateHdr **start, uint32_t *size) 326 { 327 const uint32_t *rsaKey, *osSigHash, *osSigPubkey, *ourHash, *rsaResult, *expectedHash = NULL; 328 struct OsUpdateHdr *hdr = (struct OsUpdateHdr*)addr; 329 struct OsUpdateHdr cpy; 330 uint32_t i, numRsaKeys = 0, rsaStateVar1, rsaStateVar2, rsaStep = 0; 331 const uint8_t *updateBinaryData; 332 bool isValid = false; 333 struct Sha2state sha; 334 struct RsaState rsa; 335 uint32_t ret = OS_UPDT_HDR_CHECK_FAILED; 336 const uint32_t overhead = sizeof(*hdr) + 2 * RSA_WORDS; 337 338 // header does not fit or is not aligned 339 if (addr < __shared_start || addr > (__shared_end - overhead) || ((uintptr_t)addr & 3)) 340 return OS_UPDT_HDR_CHECK_FAILED; 341 342 // image does not fit 343 if (hdr->size > (__shared_end - addr - overhead)) 344 return OS_UPDT_HDR_CHECK_FAILED; 345 346 // OS magic does not match 347 if (memcmp(hdr->magic, mOsUpdateMagic, sizeof(hdr->magic)) != 0) 348 return OS_UPDT_HDR_CHECK_FAILED; 349 350 // we don't allow shortcuts on success path, but we want to fail quickly 351 if (hdr->marker == OS_UPDT_MARKER_INVALID) 352 return OS_UPDT_HDR_MARKER_INVALID; 353 354 // download did not finish 355 if (hdr->marker == OS_UPDT_MARKER_INPROGRESS) 356 return OS_UPDT_HDR_MARKER_INVALID; 357 358 //get pointers 359 updateBinaryData = (const uint8_t*)(hdr + 1); 360 osSigHash = (const uint32_t*)(updateBinaryData + hdr->size); 361 osSigPubkey = osSigHash + RSA_WORDS; 362 363 //make sure the pub key is known 364 for (i = 0, rsaKey = blExtApiGetRsaKeyInfo(&numRsaKeys); i < numRsaKeys; i++, rsaKey += RSA_WORDS) { 365 if (memcmp(rsaKey, osSigPubkey, RSA_BYTES) == 0) 366 break; 367 } 368 369 if (i == numRsaKeys) { 370 ret = OS_UPDT_UNKNOWN_PUBKEY; 371 //signed with an unknown key -> fail 372 goto fail; 373 } 374 375 //decode sig using pubkey 376 do { 377 rsaResult = rsaPubOpIterative(&rsa, osSigHash, osSigPubkey, &rsaStateVar1, &rsaStateVar2, &rsaStep); 378 } while (rsaStep); 379 380 if (!rsaResult) { 381 //decode fails -> invalid sig 382 ret = OS_UPDT_INVALID_SIGNATURE; 383 goto fail; 384 } 385 386 //verify padding 387 expectedHash = blExtApiSigPaddingVerify(rsaResult); 388 389 if (!expectedHash) { 390 //padding check fails -> invalid sig 391 ret = OS_UPDT_INVALID_SIGNATURE_HASH; 392 goto fail; 393 } 394 395 //hash the update 396 sha2init(&sha); 397 398 memcpy(&cpy, hdr, sizeof(cpy)); 399 cpy.marker = OS_UPDT_MARKER_INPROGRESS; 400 sha2processBytes(&sha, &cpy, sizeof(cpy)); 401 sha2processBytes(&sha, (uint8_t*)(hdr + 1), hdr->size); 402 ourHash = sha2finish(&sha); 403 404 //verify hash match 405 if (memcmp(expectedHash, ourHash, SHA2_HASH_SIZE) != 0) { 406 //hash does not match -> data tampered with 407 ret = OS_UPDT_INVALID_SIGNATURE_HASH; // same error; do not disclose nature of hash problem 408 goto fail; 409 } 410 411 //it is valid 412 isValid = true; 413 ret = OS_UPDT_SUCCESS; 414 if (start) 415 *start = hdr; 416 if (size) 417 *size = hdr->size; 418 419 fail: 420 //mark it appropriately 421 blWriteMark(hdr, isValid ? OS_UPDT_MARKER_VERIFIED : OS_UPDT_MARKER_INVALID); 422 return ret; 423 } 424 425 static inline bool blUpdateVerify() 426 { 427 return blVerifyOsImage(__shared_start, NULL, NULL) == OS_UPDT_SUCCESS; 428 } 429 430 static uint8_t blLoaderRxByte() 431 { 432 return blSpiTxRxByte(0); 433 } 434 435 static void blLoaderTxByte(uint32_t val) 436 { 437 blSpiTxRxByte(val); 438 } 439 440 static void blLoaderTxBytes(const void *data, uint32_t len) 441 { 442 const uint8_t *buf = (const uint8_t*)data; 443 444 blLoaderTxByte(len - 1); 445 while (len--) 446 blLoaderTxByte(*buf++); 447 } 448 449 static bool blLoaderSendSyncOut() 450 { 451 return blSpiTxRxByte(BL_SYNC_OUT) == BL_SYNC_IN; 452 } 453 454 static bool blLoaderSendAck(bool ack) 455 { 456 blLoaderRxByte(); 457 blLoaderTxByte(ack ? BL_ACK : BL_NAK); 458 return blLoaderRxByte() == BL_ACK; 459 } 460 461 static uint32_t blLoaderRxCmd() 462 { 463 uint8_t cmd = blLoaderRxByte(); 464 uint8_t cmdNot = blSpiTxRxByte(BL_ACK); 465 return (cmd ^ cmdNot) == 0xFF ? cmd : BL_ERROR; 466 } 467 468 static void blLoader(bool force) 469 { 470 bool seenErase = false; 471 uint32_t nextAddr = 0; 472 uint32_t expectedSize = 0; 473 474 blSetup(); 475 476 //if int pin is not low, do not bother any further 477 if (blHostActive() || force) { 478 479 blConfigIo(); 480 481 //if we saw a sync, do the bootloader thing 482 if (blSyncWait(BL_SYNC_IN)) { 483 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}; 484 uint32_t allSizes[] = {__builtin_bswap32(__code_end - __code_start), __builtin_bswap32(__shared_end - __shared_start), __builtin_bswap32(__eedata_end - __eedata_start)}; 485 bool ack = true; //we ack the sync 486 487 ack = blLoaderSendSyncOut(); 488 489 //loop forever listening to commands 490 while (1) { 491 uint32_t sync, cmd, addr = 0, len, checksum = 0, i; 492 uint8_t data[256]; 493 494 //send ack or NAK for last thing 495 if (!blLoaderSendAck(ack)) 496 goto out; 497 498 while ((sync = blLoaderRxByte()) != BL_SYNC_IN); 499 cmd = blLoaderRxCmd(); 500 501 ack = false; 502 if (sync == BL_SYNC_IN && cmd != BL_ERROR) 503 switch (cmd) { 504 case BL_CMD_GET: 505 506 //ACK the command 507 (void)blLoaderSendAck(true); 508 509 blLoaderTxBytes(supportedCmds, sizeof(supportedCmds)); 510 ack = true; 511 break; 512 513 case BL_CMD_READ_MEM: 514 if (!seenErase) //no reading till we erase the shared area (this way we do not leak encrypted apps' plaintexts) 515 break; 516 517 //ACK the command 518 (void)blLoaderSendAck(true); 519 520 //get address 521 for (i = 0; i < 4; i++) { 522 uint32_t byte = blLoaderRxByte(); 523 checksum ^= byte; 524 addr = (addr << 8) + byte; 525 } 526 527 //reject addresses outside of our fake area or on invalid checksum 528 if (blLoaderRxByte() != checksum || addr < BL_SHARED_AREA_FAKE_ADDR || addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) 529 break; 530 531 //ack the address 532 (void)blLoaderSendAck(true); 533 534 //get the length 535 len = blLoaderRxByte(); 536 537 //reject invalid checksum 538 if (blLoaderRxByte() != (uint8_t)~len || addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) 539 break; 540 541 len++; 542 543 //reject reads past the end of the shared area 544 if (addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) 545 break; 546 547 //ack the length 548 (void)blLoaderSendAck(true); 549 550 //read the data & send it 551 blLoaderTxBytes(__shared_start + addr - BL_SHARED_AREA_FAKE_ADDR, len); 552 ack = true; 553 break; 554 555 case BL_CMD_WRITE_MEM: 556 if (!seenErase) //no writing till we erase the shared area (this way we do not purposefully modify encrypted apps' plaintexts in a nefarious fashion) 557 break; 558 559 //ACK the command 560 (void)blLoaderSendAck(true); 561 562 //get address 563 for (i = 0; i < 4; i++) { 564 uint32_t byte = blLoaderRxByte(); 565 checksum ^= byte; 566 addr = (addr << 8) + byte; 567 } 568 569 //reject addresses outside of our fake area or on invalid checksum 570 if (blLoaderRxByte() != checksum || 571 addr < BL_SHARED_AREA_FAKE_ADDR || 572 addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) 573 break; 574 575 addr -= BL_SHARED_AREA_FAKE_ADDR; 576 if (addr != nextAddr) 577 break; 578 579 //ack the address 580 (void)blLoaderSendAck(true); 581 582 //get the length 583 checksum = len = blLoaderRxByte(); 584 len++; 585 586 //get bytes 587 for (i = 0; i < len; i++) { 588 uint32_t byte = blLoaderRxByte(); 589 checksum ^= byte; 590 data[i] = byte; 591 } 592 593 //reject writes that takes out outside fo shared area or invalid checksums 594 if (blLoaderRxByte() != checksum || addr + len > __shared_end - __shared_start) 595 break; 596 597 // OBSOLETE: superseded by sequential contiguous write requirement 598 //if (addr && addr < sizeof(struct OsUpdateHdr)) 599 // break; 600 601 //a write starting at zero must be big enough to contain a full OS update header 602 if (!addr) { 603 const struct OsUpdateHdr *hdr = (const struct OsUpdateHdr*)data; 604 605 //verify it is at least as big as the header 606 if (len < sizeof(struct OsUpdateHdr)) 607 break; 608 609 //check for magic 610 for (i = 0; i < sizeof(hdr->magic) && hdr->magic[i] == mOsUpdateMagic[i]; i++); 611 612 //verify magic check passed & marker is properly set to inprogress 613 if (i != sizeof(hdr->magic) || hdr->marker != OS_UPDT_MARKER_INPROGRESS) 614 break; 615 expectedSize = sizeof(*hdr) + hdr->size + 2 * RSA_BYTES; 616 } 617 if (addr + len > expectedSize) 618 break; 619 620 //do it 621 ack = blExtApiProgramSharedArea(__shared_start + addr, data, len, BL_FLASH_KEY1, BL_FLASH_KEY2); 622 blResetRxData(); 623 nextAddr += len; 624 break; 625 626 case BL_CMD_ERASE: 627 628 //ACK the command 629 (void)blLoaderSendAck(true); 630 631 //get address 632 for (i = 0; i < 2; i++) { 633 uint32_t byte = blLoaderRxByte(); 634 checksum ^= byte; 635 addr = (addr << 8) + byte; 636 } 637 638 //reject addresses that are not our magic address or on invalid checksum 639 if (blLoaderRxByte() != checksum || addr != BL_SHARED_AREA_FAKE_ERASE_BLK) 640 break; 641 642 //do it 643 ack = blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2); 644 if (ack) { 645 seenErase = true; 646 nextAddr = 0; 647 expectedSize = 0; 648 } 649 blResetRxData(); 650 break; 651 652 case BL_CMD_GET_SIZES: 653 654 //ACK the command 655 (void)blLoaderSendAck(true); 656 657 blLoaderTxBytes(allSizes, sizeof(allSizes)); 658 break; 659 660 case BL_CMD_UPDATE_FINISHED: 661 blUpdateMark(OS_UPDT_MARKER_INPROGRESS, OS_UPDT_MARKER_DOWNLOADED); 662 ack = blUpdateVerify(); 663 break; 664 } 665 } 666 } 667 } 668 669 out: 670 blCleanup(); 671 } 672 673 void blMain(uint32_t appBase) 674 { 675 bool forceLoad = false; 676 677 blLog("NanohubOS bootloader up @ %p\n", &blMain); 678 679 //enter SPI loader if requested 680 do { 681 uint32_t res; 682 struct OsUpdateHdr *os; 683 684 blLoader(forceLoad); 685 res = blVerifyOsUpdate(&os, NULL); 686 if (res == OS_UPDT_SUCCESS) 687 blApplyVerifiedUpdate(os); 688 else if (res != OS_UPDT_HDR_CHECK_FAILED) 689 blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2); 690 691 forceLoad = true; 692 } while (*(volatile uint32_t*)appBase == 0xFFFFFFFF); 693 } 694 695 const struct BlApiTable __attribute__((section(".blapi"))) __BL_API = 696 { 697 .blGetVersion = &blExtApiGetVersion, 698 .blReboot = &blExtApiReboot, 699 .blGetSnum = &blExtApiGetSnum, 700 .blProgramShared = &blExtApiProgramSharedArea, 701 .blEraseShared = &blExtApiEraseSharedArea, 702 .blProgramEe = &blExtApiProgramEe, 703 .blGetPubKeysInfo = &blExtApiGetRsaKeyInfo, 704 .blRsaPubOpIterative = &rsaPubOpIterative, 705 .blSha2init = &sha2init, 706 .blSha2processBytes = &sha2processBytes, 707 .blSha2finish = &sha2finish, 708 .blAesInitForEncr = &aesInitForEncr, 709 .blAesInitForDecr = &aesInitForDecr, 710 .blAesEncr = &aesEncr, 711 .blAesDecr = &aesDecr, 712 .blAesCbcInitForEncr = &aesCbcInitForEncr, 713 .blAesCbcInitForDecr = &aesCbcInitForDecr, 714 .blAesCbcEncr = &aesCbcEncr, 715 .blAesCbcDecr = &aesCbcDecr, 716 .blSigPaddingVerify = &blExtApiSigPaddingVerify, 717 .blVerifyOsUpdate = &blExtApiVerifyOsUpdate, 718 }; 719