What changed, and why it matters
This commit adds a new pre-built bootloader release (version 3.3.0) for the COLDCARD Mk4 hardware wallet. It consists of binary firmware files and a hash manifest, plus a disassembly listing. There is no source code change, no vulnerability description, and no indication of a security fix or bug. It appears to be a routine release artifact drop.
No action required based solely on this commit. If reviewing for supply-chain assurance, verify the published hashes against a reproducible build and confirm the README changelog for 3.3.0.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds the directory stm32/mk4-bootloader/releases/3.3.0/ containing bootloader.bin, bootloader.dfu, bootloader.lss, and a 3.3.0.txt manifest with SHA-256 hashes and build metadata. The README was also updated (binary diff only). The .lss file is an ARM disassembly of the bootloader ELF, showing normal startup, firewall/SYSCFG setup, OLED/SPI initialization, GPIO, flash protection, and dispatch routines. No source code is modified, no patch is applied, and no security-relevant change is described in the commit message or files.
Changed components
stm32/mk4-bootloader/releases/3.3.0/bootloader.binstm32/mk4-bootloader/releases/3.3.0/bootloader.dfustm32/mk4-bootloader/releases/3.3.0/bootloader.lssstm32/mk4-bootloader/releases/3.3.0.txtstm32/mk4-bootloader/releases/README.mdInspect captured patch +34698 / −0
diff --git a/stm32/mk4-bootloader/releases/3.3.0.txt b/stm32/mk4-bootloader/releases/3.3.0.txt
new file mode 100644
index 0000000..ae53219
--- /dev/null
+++ b/stm32/mk4-bootloader/releases/3.3.0.txt
@@ -0,0 +1,4 @@
+97c72e22f99e347e1d03c0f4b558f16c5cb6e1164e02efd86bf702c4deb19487 bootloader.dfu
+6bb9350a650f6268e84a5126ae2816ef6fe9d37c3baefecdf806907c43c43618 bootloader.bin
+425dee4c9e849a282a643e6f731b672ddfeab21e4fba3c756891a98e6d2e6001 bootloader.lss
+3.3.0 time=20260305.091240 git=master@e35f60ed
diff --git a/stm32/mk4-bootloader/releases/3.3.0/bootloader.bin b/stm32/mk4-bootloader/releases/3.3.0/bootloader.bin
new file mode 100644
index 0000000..cde2226
Binary files /dev/null and b/stm32/mk4-bootloader/releases/3.3.0/bootloader.bin differ
diff --git a/stm32/mk4-bootloader/releases/3.3.0/bootloader.dfu b/stm32/mk4-bootloader/releases/3.3.0/bootloader.dfu
new file mode 100644
index 0000000..709a842
Binary files /dev/null and b/stm32/mk4-bootloader/releases/3.3.0/bootloader.dfu differ
diff --git a/stm32/mk4-bootloader/releases/3.3.0/bootloader.lss b/stm32/mk4-bootloader/releases/3.3.0/bootloader.lss
new file mode 100644
index 0000000..b388a59
--- /dev/null
+++ b/stm32/mk4-bootloader/releases/3.3.0/bootloader.lss
@@ -0,0 +1,34693 @@
+
+bootloader.elf: file format elf32-littlearm
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 .text 0000ead0 08000000 08000000 00010000 2**8
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 1 .relocate 00000150 2009e000 0800ead0 0002e000 2**2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 .bss 000002e8 2009e150 0800ec20 0002e150 2**2
+ ALLOC
+ 3 .stack 00000800 2009e438 0800ef08 0002e150 2**0
+ ALLOC
+ 4 .debug_info 0002bd2d 00000000 00000000 0002e150 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 5 .debug_abbrev 00005f71 00000000 00000000 00059e7d 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 6 .debug_loc 00014618 00000000 00000000 0005fdee 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 7 .debug_aranges 000010d0 00000000 00000000 00074406 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 8 .debug_ranges 00002168 00000000 00000000 000754d6 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 9 .debug_macro 0003253d 00000000 00000000 0007763e 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 10 .debug_line 0001dece 00000000 00000000 000a9b7b 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 11 .debug_str 0011cbf4 00000000 00000000 000c7a49 2**0
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+ 12 .comment 00000049 00000000 00000000 001e463d 2**0
+ CONTENTS, READONLY
+ 13 .ARM.attributes 00000032 00000000 00000000 001e4686 2**0
+ CONTENTS, READONLY
+ 14 .debug_frame 00003714 00000000 00000000 001e46b8 2**2
+ CONTENTS, READONLY, DEBUGGING, OCTETS
+
+Disassembly of section .text:
+
+08000000 <_sfixed>:
+ 8000000: 200a0000 .word 0x200a0000
+ 8000004: 080000b5 .word 0x080000b5
+ 8000008: 0800001d .word 0x0800001d
+ 800000c: 0800001f .word 0x0800001f
+ 8000010: 08000021 .word 0x08000021
+ 8000014: 08000023 .word 0x08000023
+ 8000018: 08000025 .word 0x08000025
+
+0800001c <NMI_Handler>:
+ 800001c: be01 bkpt 0x0001
+
+0800001e <HardFault_Handler>:
+ 800001e: be02 bkpt 0x0002
+
+08000020 <MemManage_Handler>:
+ 8000020: be03 bkpt 0x0003
+
+08000022 <BusFault_Handler>:
+ 8000022: be04 bkpt 0x0004
+
+08000024 <UsageFault_Handler>:
+ 8000024: be05 bkpt 0x0005
+ 8000026: e7fe b.n 8000026 <UsageFault_Handler+0x2>
+
+08000028 <bootloader_info>:
+ ...
+ 8000040: 08000305 .word 0x08000305
+
+08000044 <my_version_code>:
+ 8000044: 00000200 .word 0x00000200
+ ...
+ 8000060: 20296328 .word 0x20296328
+ 8000064: 79706f43 .word 0x79706f43
+ 8000068: 68676972 .word 0x68676972
+ 800006c: 30322074 .word 0x30322074
+ 8000070: 322d3831 .word 0x322d3831
+ 8000074: 20323230 .word 0x20323230
+ 8000078: 43207962 .word 0x43207962
+ 800007c: 6b6e696f .word 0x6b6e696f
+ 8000080: 20657469 .word 0x20657469
+ 8000084: 2e636e49 .word 0x2e636e49
+ 8000088: 0a200a20 .word 0x0a200a20
+ 800008c: 73696854 .word 0x73696854
+ 8000090: 61707320 .word 0x61707320
+ 8000094: 66206563 .word 0x66206563
+ 8000098: 7220726f .word 0x7220726f
+ 800009c: 21746e65 .word 0x21746e65
+ 80000a0: 73754a20 .word 0x73754a20
+ 80000a4: 42312074 .word 0x42312074
+ 80000a8: 792f4354 .word 0x792f4354
+ 80000ac: 2e726165 .word 0x2e726165
+ 80000b0: 0a200a20 .word 0x0a200a20
+
+080000b4 <reset_entry>:
+ 80000b4: f000 f816 bl 80000e4 <firewall_setup>
+ 80000b8: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff
+ 80000bc: f04f 0100 mov.w r1, #0
+ 80000c0: f04f 0200 mov.w r2, #0
+ 80000c4: f04f 0300 mov.w r3, #0
+ 80000c8: f000 f91c bl 8000304 <callgate_entry0>
+ 80000cc: f248 0120 movw r1, #32800 ; 0x8020
+ 80000d0: ea4f 3101 mov.w r1, r1, lsl #12
+ 80000d4: 6808 ldr r0, [r1, #0]
+ 80000d6: 4685 mov sp, r0
+ 80000d8: f04f 0001 mov.w r0, #1
+ 80000dc: f8d1 e004 ldr.w lr, [r1, #4]
+ 80000e0: 4770 bx lr
+ ...
+
+080000e4 <firewall_setup>:
+ void
+firewall_setup(void)
+{
+ // This is critical: without the clock enabled to "SYSCFG" we
+ // can't tell the FW is enabled or not! Enabling it would also not work
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 80000e4: 4b1b ldr r3, [pc, #108] ; (8000154 <firewall_setup+0x70>)
+{
+ 80000e6: b500 push {lr}
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 80000e8: 6e1a ldr r2, [r3, #96] ; 0x60
+ 80000ea: f042 0201 orr.w r2, r2, #1
+ 80000ee: 661a str r2, [r3, #96] ; 0x60
+ 80000f0: 6e1b ldr r3, [r3, #96] ; 0x60
+{
+ 80000f2: b08b sub sp, #44 ; 0x2c
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 80000f4: f003 0301 and.w r3, r3, #1
+ 80000f8: 9300 str r3, [sp, #0]
+ 80000fa: 9b00 ldr r3, [sp, #0]
+
+ if(__HAL_FIREWALL_IS_ENABLED()) {
+ 80000fc: 4b16 ldr r3, [pc, #88] ; (8000158 <firewall_setup+0x74>)
+ 80000fe: 685b ldr r3, [r3, #4]
+ 8000100: 07db lsls r3, r3, #31
+ 8000102: d524 bpl.n 800014e <firewall_setup+0x6a>
+ // REMINDERS:
+ // - cannot debug anything in boot loader w/ firewall enabled (no readback, no bkpt)
+ // - when RDP=2, this protection still important or else python can read pairing secret
+ // - in factory mode (RDP!=2), it's nice to have this disabled so we can debug still
+ // - could look at RDP level here, but it would be harder to completely reset the bag number!
+ if(check_all_ones_raw(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))) {
+ 8000104: 4815 ldr r0, [pc, #84] ; (800015c <firewall_setup+0x78>)
+ 8000106: 2120 movs r1, #32
+ 8000108: f002 fac4 bl 8002694 <check_all_ones_raw>
+ 800010c: b9f8 cbnz r0, 800014e <firewall_setup+0x6a>
+ // for debug builds, never enable firewall
+ return;
+#endif
+
+ extern int firewall_starts; // see startup.S ... aligned@256 (0x08000300)
+ uint32_t start = (uint32_t)&firewall_starts;
+ 800010e: 4b14 ldr r3, [pc, #80] ; (8000160 <firewall_setup+0x7c>)
+ uint32_t len = BL_FLASH_SIZE - (start - BL_FLASH_BASE);
+ 8000110: 4a14 ldr r2, [pc, #80] ; (8000164 <firewall_setup+0x80>)
+ // but sensitive stuff is still there (which would allow bypass)
+ // - so it's important to enable option bytes to set write-protect flash of entire bootloader
+ // - to disable debug and complete protection, must enable write-protect "level 2" (RDP=2)
+ //
+
+ FIREWALL_InitTypeDef init = {
+ 8000112: 9302 str r3, [sp, #8]
+ uint32_t len = BL_FLASH_SIZE - (start - BL_FLASH_BASE);
+ 8000114: 1ad3 subs r3, r2, r3
+ FIREWALL_InitTypeDef init = {
+ 8000116: e9cd 3203 strd r3, r2, [sp, #12]
+ 800011a: f44f 4380 mov.w r3, #16384 ; 0x4000
+ 800011e: e9cd 3005 strd r3, r0, [sp, #20]
+ 8000122: e9cd 0007 strd r0, r0, [sp, #28]
+ 8000126: 9009 str r0, [sp, #36] ; 0x24
+ .VDataSegmentLength = 0,
+ .VolatileDataExecution = 0,
+ .VolatileDataShared = 0,
+ };
+
+ int rv = HAL_FIREWALL_Config((FIREWALL_InitTypeDef *)&init);
+ 8000128: a802 add r0, sp, #8
+ 800012a: f000 f821 bl 8000170 <HAL_FIREWALL_Config>
+ if(rv) {
+ 800012e: b110 cbz r0, 8000136 <firewall_setup+0x52>
+ INCONSISTENT("fw");
+ 8000130: 480d ldr r0, [pc, #52] ; (8000168 <firewall_setup+0x84>)
+ 8000132: f000 fc89 bl 8000a48 <fatal_error>
+ }
+
+ __HAL_FIREWALL_PREARM_DISABLE();
+ 8000136: 4b0d ldr r3, [pc, #52] ; (800016c <firewall_setup+0x88>)
+ 8000138: 6a1a ldr r2, [r3, #32]
+ 800013a: f022 0201 bic.w r2, r2, #1
+ 800013e: 621a str r2, [r3, #32]
+ 8000140: 6a1b ldr r3, [r3, #32]
+ 8000142: f003 0301 and.w r3, r3, #1
+ 8000146: 9301 str r3, [sp, #4]
+ 8000148: 9b01 ldr r3, [sp, #4]
+ HAL_FIREWALL_EnableFirewall();
+ 800014a: f000 f88b bl 8000264 <HAL_FIREWALL_EnableFirewall>
+}
+ 800014e: b00b add sp, #44 ; 0x2c
+ 8000150: f85d fb04 ldr.w pc, [sp], #4
+ 8000154: 40021000 .word 0x40021000
+ 8000158: 40010000 .word 0x40010000
+ 800015c: 0801c050 .word 0x0801c050
+ 8000160: 08000300 .word 0x08000300
+ 8000164: 0801c000 .word 0x0801c000
+ 8000168: 0800d760 .word 0x0800d760
+ 800016c: 40011c00 .word 0x40011c00
+
+08000170 <HAL_FIREWALL_Config>:
+ * @param fw_init: Firewall initialization structure
+ * @note The API returns HAL_ERROR if the Firewall is already enabled.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init)
+{
+ 8000170: b573 push {r0, r1, r4, r5, r6, lr}
+ /* Check the Firewall initialization structure allocation */
+ if(fw_init == NULL)
+ 8000172: b910 cbnz r0, 800017a <HAL_FIREWALL_Config+0xa>
+ {
+ return HAL_ERROR;
+ 8000174: 2001 movs r0, #1
+ /* Set Firewall Configuration Register VDE and VDS bits
+ (volatile data execution and shared configuration) */
+ MODIFY_REG(FIREWALL->CR, FW_CR_VDS|FW_CR_VDE, fw_init->VolatileDataExecution|fw_init->VolatileDataShared);
+
+ return HAL_OK;
+}
+ 8000176: b002 add sp, #8
+ 8000178: bd70 pop {r4, r5, r6, pc}
+ __HAL_RCC_FIREWALL_CLK_ENABLE();
+ 800017a: 4b19 ldr r3, [pc, #100] ; (80001e0 <HAL_FIREWALL_Config+0x70>)
+ 800017c: 6e1a ldr r2, [r3, #96] ; 0x60
+ 800017e: f042 0280 orr.w r2, r2, #128 ; 0x80
+ 8000182: 661a str r2, [r3, #96] ; 0x60
+ 8000184: 6e1b ldr r3, [r3, #96] ; 0x60
+ 8000186: f003 0380 and.w r3, r3, #128 ; 0x80
+ 800018a: 9301 str r3, [sp, #4]
+ 800018c: 9b01 ldr r3, [sp, #4]
+ if (__HAL_FIREWALL_IS_ENABLED() != RESET)
+ 800018e: 4b15 ldr r3, [pc, #84] ; (80001e4 <HAL_FIREWALL_Config+0x74>)
+ 8000190: 685b ldr r3, [r3, #4]
+ 8000192: 07db lsls r3, r3, #31
+ 8000194: d5ee bpl.n 8000174 <HAL_FIREWALL_Config+0x4>
+ if (fw_init->CodeSegmentLength != 0U)
+ 8000196: 6841 ldr r1, [r0, #4]
+ if (fw_init->NonVDataSegmentLength < 0x100U)
+ 8000198: 68c2 ldr r2, [r0, #12]
+ if (fw_init->CodeSegmentLength != 0U)
+ 800019a: b109 cbz r1, 80001a0 <HAL_FIREWALL_Config+0x30>
+ if (fw_init->NonVDataSegmentLength < 0x100U)
+ 800019c: 2aff cmp r2, #255 ; 0xff
+ 800019e: d9e9 bls.n 8000174 <HAL_FIREWALL_Config+0x4>
+ WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress));
+ 80001a0: 6803 ldr r3, [r0, #0]
+ 80001a2: 4e11 ldr r6, [pc, #68] ; (80001e8 <HAL_FIREWALL_Config+0x78>)
+ if (fw_init->VDataSegmentLength != 0U)
+ 80001a4: 6944 ldr r4, [r0, #20]
+ WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress));
+ 80001a6: ea03 0506 and.w r5, r3, r6
+ 80001aa: 4b10 ldr r3, [pc, #64] ; (80001ec <HAL_FIREWALL_Config+0x7c>)
+ 80001ac: 601d str r5, [r3, #0]
+ WRITE_REG(FIREWALL->CSL, (FW_CSL_LENG & fw_init->CodeSegmentLength));
+ 80001ae: 4d10 ldr r5, [pc, #64] ; (80001f0 <HAL_FIREWALL_Config+0x80>)
+ 80001b0: 4029 ands r1, r5
+ 80001b2: 6059 str r1, [r3, #4]
+ WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress));
+ 80001b4: 6881 ldr r1, [r0, #8]
+ WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength));
+ 80001b6: 402a ands r2, r5
+ WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress));
+ 80001b8: 4031 ands r1, r6
+ 80001ba: 6099 str r1, [r3, #8]
+ WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength));
+ 80001bc: 60da str r2, [r3, #12]
+ WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress));
+ 80001be: 6901 ldr r1, [r0, #16]
+ 80001c0: 4a0c ldr r2, [pc, #48] ; (80001f4 <HAL_FIREWALL_Config+0x84>)
+ 80001c2: 4011 ands r1, r2
+ WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength));
+ 80001c4: 4022 ands r2, r4
+ WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress));
+ 80001c6: 6119 str r1, [r3, #16]
+ WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength));
+ 80001c8: 615a str r2, [r3, #20]
+ MODIFY_REG(FIREWALL->CR, FW_CR_VDS|FW_CR_VDE, fw_init->VolatileDataExecution|fw_init->VolatileDataShared);
+ 80001ca: e9d0 2006 ldrd r2, r0, [r0, #24]
+ 80001ce: 6a19 ldr r1, [r3, #32]
+ 80001d0: 4302 orrs r2, r0
+ 80001d2: f021 0106 bic.w r1, r1, #6
+ 80001d6: 430a orrs r2, r1
+ 80001d8: 621a str r2, [r3, #32]
+ return HAL_OK;
+ 80001da: 2000 movs r0, #0
+ 80001dc: e7cb b.n 8000176 <HAL_FIREWALL_Config+0x6>
+ 80001de: bf00 nop
+ 80001e0: 40021000 .word 0x40021000
+ 80001e4: 40010000 .word 0x40010000
+ 80001e8: 00ffff00 .word 0x00ffff00
+ 80001ec: 40011c00 .word 0x40011c00
+ 80001f0: 003fff00 .word 0x003fff00
+ 80001f4: 0003ffc0 .word 0x0003ffc0
+
+080001f8 <HAL_FIREWALL_GetConfig>:
+void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)
+{
+
+ /* Enable Firewall clock, in case no Firewall configuration has been carried
+ out up to this point */
+ __HAL_RCC_FIREWALL_CLK_ENABLE();
+ 80001f8: 4b15 ldr r3, [pc, #84] ; (8000250 <HAL_FIREWALL_GetConfig+0x58>)
+ 80001fa: 6e1a ldr r2, [r3, #96] ; 0x60
+{
+ 80001fc: b573 push {r0, r1, r4, r5, r6, lr}
+ __HAL_RCC_FIREWALL_CLK_ENABLE();
+ 80001fe: f042 0280 orr.w r2, r2, #128 ; 0x80
+ 8000202: 661a str r2, [r3, #96] ; 0x60
+ 8000204: 6e1b ldr r3, [r3, #96] ; 0x60
+
+ /* Retrieve code segment protection setting */
+ fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD);
+ 8000206: 4e13 ldr r6, [pc, #76] ; (8000254 <HAL_FIREWALL_GetConfig+0x5c>)
+ fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG);
+ 8000208: 4d13 ldr r5, [pc, #76] ; (8000258 <HAL_FIREWALL_GetConfig+0x60>)
+ __HAL_RCC_FIREWALL_CLK_ENABLE();
+ 800020a: f003 0380 and.w r3, r3, #128 ; 0x80
+ 800020e: 9301 str r3, [sp, #4]
+ 8000210: 9b01 ldr r3, [sp, #4]
+ fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD);
+ 8000212: 4b12 ldr r3, [pc, #72] ; (800025c <HAL_FIREWALL_GetConfig+0x64>)
+ 8000214: 681a ldr r2, [r3, #0]
+ 8000216: 4032 ands r2, r6
+ 8000218: 6002 str r2, [r0, #0]
+ fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG);
+ 800021a: 685c ldr r4, [r3, #4]
+ 800021c: 402c ands r4, r5
+ 800021e: 6044 str r4, [r0, #4]
+
+ /* Retrieve non volatile data segment protection setting */
+ fw_config->NonVDataSegmentStartAddress = (READ_REG(FIREWALL->NVDSSA) & FW_NVDSSA_ADD);
+ 8000220: 6899 ldr r1, [r3, #8]
+ fw_config->NonVDataSegmentLength = (READ_REG(FIREWALL->NVDSL) & FW_NVDSL_LENG);
+
+ /* Retrieve volatile data segment protection setting */
+ fw_config->VDataSegmentStartAddress = (READ_REG(FIREWALL->VDSSA) & FW_VDSSA_ADD);
+ 8000222: 4c0f ldr r4, [pc, #60] ; (8000260 <HAL_FIREWALL_GetConfig+0x68>)
+ fw_config->NonVDataSegmentStartAddress = (READ_REG(FIREWALL->NVDSSA) & FW_NVDSSA_ADD);
+ 8000224: 4031 ands r1, r6
+ 8000226: 6081 str r1, [r0, #8]
+ fw_config->NonVDataSegmentLength = (READ_REG(FIREWALL->NVDSL) & FW_NVDSL_LENG);
+ 8000228: 68da ldr r2, [r3, #12]
+ 800022a: 402a ands r2, r5
+ 800022c: 60c2 str r2, [r0, #12]
+ fw_config->VDataSegmentStartAddress = (READ_REG(FIREWALL->VDSSA) & FW_VDSSA_ADD);
+ 800022e: 6919 ldr r1, [r3, #16]
+ 8000230: 4021 ands r1, r4
+ 8000232: 6101 str r1, [r0, #16]
+ fw_config->VDataSegmentLength = (READ_REG(FIREWALL->VDSL) & FW_VDSL_LENG);
+ 8000234: 695a ldr r2, [r3, #20]
+ 8000236: 4022 ands r2, r4
+ 8000238: 6142 str r2, [r0, #20]
+
+ /* Retrieve volatile data execution setting */
+ fw_config->VolatileDataExecution = (READ_REG(FIREWALL->CR) & FW_CR_VDE);
+ 800023a: 6a1a ldr r2, [r3, #32]
+ 800023c: f002 0204 and.w r2, r2, #4
+ 8000240: 6182 str r2, [r0, #24]
+
+ /* Retrieve volatile data shared setting */
+ fw_config->VolatileDataShared = (READ_REG(FIREWALL->CR) & FW_CR_VDS);
+ 8000242: 6a1b ldr r3, [r3, #32]
+ 8000244: f003 0302 and.w r3, r3, #2
+ 8000248: 61c3 str r3, [r0, #28]
+
+ return;
+}
+ 800024a: b002 add sp, #8
+ 800024c: bd70 pop {r4, r5, r6, pc}
+ 800024e: bf00 nop
+ 8000250: 40021000 .word 0x40021000
+ 8000254: 00ffff00 .word 0x00ffff00
+ 8000258: 003fff00 .word 0x003fff00
+ 800025c: 40011c00 .word 0x40011c00
+ 8000260: 0003ffc0 .word 0x0003ffc0
+
+08000264 <HAL_FIREWALL_EnableFirewall>:
+ * @retval None
+ */
+void HAL_FIREWALL_EnableFirewall(void)
+{
+ /* Clears FWDIS bit of SYSCFG CFGR1 register */
+ CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FWDIS);
+ 8000264: 4a02 ldr r2, [pc, #8] ; (8000270 <HAL_FIREWALL_EnableFirewall+0xc>)
+ 8000266: 6853 ldr r3, [r2, #4]
+ 8000268: f023 0301 bic.w r3, r3, #1
+ 800026c: 6053 str r3, [r2, #4]
+
+}
+ 800026e: 4770 bx lr
+ 8000270: 40010000 .word 0x40010000
+
+08000274 <HAL_FIREWALL_EnablePreArmFlag>:
+ * @retval None
+ */
+void HAL_FIREWALL_EnablePreArmFlag(void)
+{
+ /* Set FPA bit */
+ SET_BIT(FIREWALL->CR, FW_CR_FPA);
+ 8000274: 4a02 ldr r2, [pc, #8] ; (8000280 <HAL_FIREWALL_EnablePreArmFlag+0xc>)
+ 8000276: 6a13 ldr r3, [r2, #32]
+ 8000278: f043 0301 orr.w r3, r3, #1
+ 800027c: 6213 str r3, [r2, #32]
+}
+ 800027e: 4770 bx lr
+ 8000280: 40011c00 .word 0x40011c00
+
+08000284 <HAL_FIREWALL_DisablePreArmFlag>:
+ * @retval None
+ */
+void HAL_FIREWALL_DisablePreArmFlag(void)
+{
+ /* Clear FPA bit */
+ CLEAR_BIT(FIREWALL->CR, FW_CR_FPA);
+ 8000284: 4a02 ldr r2, [pc, #8] ; (8000290 <HAL_FIREWALL_DisablePreArmFlag+0xc>)
+ 8000286: 6a13 ldr r3, [r2, #32]
+ 8000288: f023 0301 bic.w r3, r3, #1
+ 800028c: 6213 str r3, [r2, #32]
+}
+ 800028e: 4770 bx lr
+ 8000290: 40011c00 .word 0x40011c00
+ ...
+
+08000300 <_firewall_start>:
+ 8000300: 0f193a11 .word 0x0f193a11
+
+08000304 <callgate_entry0>:
+ 8000304: f24e 0900 movw r9, #57344 ; 0xe000
+ 8000308: f2c2 0909 movt r9, #8201 ; 0x2009
+ 800030c: f44f 5a00 mov.w sl, #8192 ; 0x2000
+ 8000310: 44ca add sl, r9
+
+08000312 <wipe_loop1>:
+ 8000312: f849 ab04 str.w sl, [r9], #4
+ 8000316: 45d1 cmp r9, sl
+ 8000318: d1fb bne.n 8000312 <wipe_loop1>
+ 800031a: 46ea mov sl, sp
+ 800031c: 46cd mov sp, r9
+ 800031e: e92d 4400 stmdb sp!, {sl, lr}
+
+08000322 <dispatcher>:
+ 8000322: f000 f841 bl 80003a8 <firewall_dispatch>
+ 8000326: e8bd 4400 ldmia.w sp!, {sl, lr}
+ 800032a: 46d5 mov sp, sl
+ 800032c: f24e 0900 movw r9, #57344 ; 0xe000
+ 8000330: f2c2 0909 movt r9, #8201 ; 0x2009
+ 8000334: f44f 5a00 mov.w sl, #8192 ; 0x2000
+ 8000338: 44ca add sl, r9
+
+0800033a <wipe_loop2>:
+ 800033a: f849 0b04 str.w r0, [r9], #4
+ 800033e: 45d1 cmp r9, sl
+ 8000340: d1fb bne.n 800033a <wipe_loop2>
+ 8000342: 4770 bx lr
+
+08000344 <__NVIC_SystemReset>:
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+__STATIC_FORCEINLINE void __DSB(void)
+{
+ __ASM volatile ("dsb 0xF":::"memory");
+ 8000344: f3bf 8f4f dsb sy
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ 8000348: 4905 ldr r1, [pc, #20] ; (8000360 <__NVIC_SystemReset+0x1c>)
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ 800034a: 4b06 ldr r3, [pc, #24] ; (8000364 <__NVIC_SystemReset+0x20>)
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ 800034c: 68ca ldr r2, [r1, #12]
+ 800034e: f402 62e0 and.w r2, r2, #1792 ; 0x700
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ 8000352: 4313 orrs r3, r2
+ 8000354: 60cb str r3, [r1, #12]
+ 8000356: f3bf 8f4f dsb sy
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ 800035a: bf00 nop
+ for(;;) /* wait until reset */
+ 800035c: e7fd b.n 800035a <__NVIC_SystemReset+0x16>
+ 800035e: bf00 nop
+ 8000360: e000ed00 .word 0xe000ed00
+ 8000364: 05fa0004 .word 0x05fa0004
+
+08000368 <good_addr>:
+good_addr(const uint8_t *b, int minlen, int len, bool readonly)
+{
+ uint32_t x = (uint32_t)b;
+
+ if(minlen) {
+ if(!b) return EFAULT; // gave no buffer
+ 8000368: b198 cbz r0, 8000392 <good_addr+0x2a>
+ if(len < minlen) return ERANGE; // too small
+ 800036a: 4291 cmp r1, r2
+ 800036c: dc13 bgt.n 8000396 <good_addr+0x2e>
+ }
+
+ if((x >= SRAM1_BASE) && ((x+len) <= BL_SRAM_BASE)) {
+ 800036e: f1b0 5f00 cmp.w r0, #536870912 ; 0x20000000
+ 8000372: d303 bcc.n 800037c <good_addr+0x14>
+ 8000374: 490b ldr r1, [pc, #44] ; (80003a4 <good_addr+0x3c>)
+ 8000376: 4402 add r2, r0
+ 8000378: 428a cmp r2, r1
+ 800037a: d90e bls.n 800039a <good_addr+0x32>
+ // ok: it's inside the SRAM areas, up to where we start
+ return 0;
+ }
+
+ if(!readonly) {
+ 800037c: b17b cbz r3, 800039e <good_addr+0x36>
+ return EPERM;
+ }
+
+ if((x >= FIRMWARE_START) && (x - FIRMWARE_START) < FW_MAX_LENGTH_MK4) {
+ 800037e: f100 4077 add.w r0, r0, #4143972352 ; 0xf7000000
+ 8000382: f500 007e add.w r0, r0, #16646144 ; 0xfe0000
+ // inside flash of main firmware (happens for QSTR's)
+ return 0;
+ }
+
+ return EACCES;
+ 8000386: f5b0 1ff0 cmp.w r0, #1966080 ; 0x1e0000
+ 800038a: bf34 ite cc
+ 800038c: 2000 movcc r0, #0
+ 800038e: 200d movcs r0, #13
+ 8000390: 4770 bx lr
+ if(!b) return EFAULT; // gave no buffer
+ 8000392: 200e movs r0, #14
+ 8000394: 4770 bx lr
+ if(len < minlen) return ERANGE; // too small
+ 8000396: 2022 movs r0, #34 ; 0x22
+ 8000398: 4770 bx lr
+ return 0;
+ 800039a: 2000 movs r0, #0
+ 800039c: 4770 bx lr
+ return EPERM;
+ 800039e: 2001 movs r0, #1
+}
+ 80003a0: 4770 bx lr
+ 80003a2: bf00 nop
+ 80003a4: 2009e000 .word 0x2009e000
+
+080003a8 <firewall_dispatch>:
+//
+ __attribute__ ((used))
+ int
+firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
+ uint32_t arg2, uint32_t incoming_sp, uint32_t incoming_lr)
+{
+ 80003a8: b570 push {r4, r5, r6, lr}
+ 80003aa: b09e sub sp, #120 ; 0x78
+ 80003ac: 460d mov r5, r1
+ 80003ae: 9c23 ldr r4, [sp, #140] ; 0x8c
+ 80003b0: 9301 str r3, [sp, #4]
+ __ASM volatile ("cpsid i" : : : "memory");
+ 80003b2: b672 cpsid i
+ // in case the caller didn't already, but would just lead to a crash anyway
+ __disable_irq();
+
+ // "1=any code executed outside the protected segment will close the Firewall"
+ // "0=.. will reset the processor"
+ __HAL_FIREWALL_PREARM_DISABLE();
+ 80003b4: 4ba5 ldr r3, [pc, #660] ; (800064c <firewall_dispatch+0x2a4>)
+ 80003b6: 6a19 ldr r1, [r3, #32]
+ 80003b8: f021 0101 bic.w r1, r1, #1
+ 80003bc: 6219 str r1, [r3, #32]
+ 80003be: 6a1b ldr r3, [r3, #32]
+ 80003c0: f003 0301 and.w r3, r3, #1
+ 80003c4: 9302 str r3, [sp, #8]
+ // using read/write in place.
+ // - use arg2 use when a simple number is needed; never a pointer!
+ // - mpy may provide a pointer to flash if we give it a qstr or small value, and if
+ // we're reading only, that's fine.
+
+ if(len_in > 1024) { // arbitrary max, increase as needed
+ 80003c6: f5b2 6f80 cmp.w r2, #1024 ; 0x400
+ __HAL_FIREWALL_PREARM_DISABLE();
+ 80003ca: 9b02 ldr r3, [sp, #8]
+ if(len_in > 1024) { // arbitrary max, increase as needed
+ 80003cc: f300 82e3 bgt.w 8000996 <firewall_dispatch+0x5ee>
+
+ // Use these macros
+#define REQUIRE_IN_ONLY(x) if((rv = good_addr(buf_io, (x), len_in, true))) { goto fail; }
+#define REQUIRE_OUT(x) if((rv = good_addr(buf_io, (x), len_in, false))) { goto fail; }
+
+ switch(method_num) {
+ 80003d0: 3001 adds r0, #1
+ 80003d2: 281c cmp r0, #28
+ 80003d4: f200 81b6 bhi.w 8000744 <firewall_dispatch+0x39c>
+ 80003d8: e8df f010 tbh [pc, r0, lsl #1]
+ 80003dc: 001d02f9 .word 0x001d02f9
+ 80003e0: 00800034 .word 0x00800034
+ 80003e4: 00d100bd .word 0x00d100bd
+ 80003e8: 01f300f2 .word 0x01f300f2
+ 80003ec: 01b401b4 .word 0x01b401b4
+ 80003f0: 01b401b4 .word 0x01b401b4
+ 80003f4: 00fa01b4 .word 0x00fa01b4
+ 80003f8: 01b401b4 .word 0x01b401b4
+ 80003fc: 01240105 .word 0x01240105
+ 8000400: 01670154 .word 0x01670154
+ 8000404: 01f701ab .word 0x01f701ab
+ 8000408: 025f0206 .word 0x025f0206
+ 800040c: 02b702a2 .word 0x02b702a2
+ 8000410: 02cf02bf .word 0x02cf02bf
+ 8000414: 02eb .short 0x02eb
+ case 0: {
+ REQUIRE_OUT(64);
+ 8000416: 2300 movs r3, #0
+ 8000418: 2140 movs r1, #64 ; 0x40
+ 800041a: 4628 mov r0, r5
+ 800041c: 9200 str r2, [sp, #0]
+ 800041e: f7ff ffa3 bl 8000368 <good_addr>
+ 8000422: 4604 mov r4, r0
+ 8000424: bb48 cbnz r0, 800047a <firewall_dispatch+0xd2>
+
+ // Return my version string
+ memset(buf_io, 0, len_in);
+ 8000426: 4601 mov r1, r0
+ 8000428: 9a00 ldr r2, [sp, #0]
+ 800042a: 4628 mov r0, r5
+ 800042c: f00d f954 bl 800d6d8 <memset>
+ strlcpy((char *)buf_io, version_string, len_in);
+ 8000430: 9a00 ldr r2, [sp, #0]
+ 8000432: 4987 ldr r1, [pc, #540] ; (8000650 <firewall_dispatch+0x2a8>)
+ 8000434: 4628 mov r0, r5
+ 8000436: f00d f96d bl 800d714 <strlcpy>
+
+ rv = strlen(version_string);
+ 800043a: 4885 ldr r0, [pc, #532] ; (8000650 <firewall_dispatch+0x2a8>)
+ 800043c: f00d f97f bl 800d73e <strlen>
+ ae_setup();
+ ae_keep_alive();
+ switch(arg2) {
+ default:
+ case 0: // read state
+ rv = ae_get_gpio();
+ 8000440: 4604 mov r4, r0
+ break;
+ 8000442: e01a b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(32);
+ 8000444: 2300 movs r3, #0
+ 8000446: 2120 movs r1, #32
+ 8000448: 4628 mov r0, r5
+ 800044a: f7ff ff8d bl 8000368 <good_addr>
+ 800044e: 4604 mov r4, r0
+ 8000450: b998 cbnz r0, 800047a <firewall_dispatch+0xd2>
+ sha256_init(&ctx);
+ 8000452: a80b add r0, sp, #44 ; 0x2c
+ 8000454: f005 f84c bl 80054f0 <sha256_init>
+ sha256_update(&ctx, (void *)&arg2, 4);
+ 8000458: 2204 movs r2, #4
+ 800045a: eb0d 0102 add.w r1, sp, r2
+ 800045e: a80b add r0, sp, #44 ; 0x2c
+ 8000460: f005 f854 bl 800550c <sha256_update>
+ sha256_update(&ctx, (void *)BL_FLASH_BASE, BL_FLASH_SIZE);
+ 8000464: f04f 6100 mov.w r1, #134217728 ; 0x8000000
+ 8000468: a80b add r0, sp, #44 ; 0x2c
+ 800046a: f44f 32e0 mov.w r2, #114688 ; 0x1c000
+ 800046e: f005 f84d bl 800550c <sha256_update>
+ sha256_final(&ctx, buf_io);
+ 8000472: 4629 mov r1, r5
+ 8000474: a80b add r0, sp, #44 ; 0x2c
+ 8000476: f005 f88f bl 8005598 <sha256_final>
+
+fail:
+
+ // Precaution: we don't want to leave SE1 authorized for any specific keys,
+ // perhaps due to an error path we didn't see. Always reset the chip.
+ ae_reset_chip();
+ 800047a: f002 faab bl 80029d4 <ae_reset_chip>
+
+ // Unlikely it matters, but clear flash memory cache.
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+ 800047e: 4b75 ldr r3, [pc, #468] ; (8000654 <firewall_dispatch+0x2ac>)
+ 8000480: 681a ldr r2, [r3, #0]
+ 8000482: f422 6280 bic.w r2, r2, #1024 ; 0x400
+ 8000486: 601a str r2, [r3, #0]
+ __HAL_FLASH_DATA_CACHE_RESET();
+ 8000488: 681a ldr r2, [r3, #0]
+ 800048a: f442 5280 orr.w r2, r2, #4096 ; 0x1000
+ 800048e: 601a str r2, [r3, #0]
+ 8000490: 681a ldr r2, [r3, #0]
+ 8000492: f422 5280 bic.w r2, r2, #4096 ; 0x1000
+ 8000496: 601a str r2, [r3, #0]
+ __HAL_FLASH_DATA_CACHE_ENABLE();
+ 8000498: 681a ldr r2, [r3, #0]
+ 800049a: f442 6280 orr.w r2, r2, #1024 ; 0x400
+ 800049e: 601a str r2, [r3, #0]
+
+ // .. and instruction memory (flash cache too?)
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+ 80004a0: 681a ldr r2, [r3, #0]
+ 80004a2: f422 7200 bic.w r2, r2, #512 ; 0x200
+ 80004a6: 601a str r2, [r3, #0]
+ __HAL_FLASH_INSTRUCTION_CACHE_RESET();
+ 80004a8: 681a ldr r2, [r3, #0]
+ 80004aa: f442 6200 orr.w r2, r2, #2048 ; 0x800
+ 80004ae: 601a str r2, [r3, #0]
+ 80004b0: 681a ldr r2, [r3, #0]
+ 80004b2: f422 6200 bic.w r2, r2, #2048 ; 0x800
+ 80004b6: 601a str r2, [r3, #0]
+ __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ 80004b8: 681a ldr r2, [r3, #0]
+ 80004ba: f442 7200 orr.w r2, r2, #512 ; 0x200
+ 80004be: 601a str r2, [r3, #0]
+
+ // authorize return from firewall into user's code
+ __HAL_FIREWALL_PREARM_ENABLE();
+ 80004c0: f5a3 3382 sub.w r3, r3, #66560 ; 0x10400
+
+ return rv;
+}
+ 80004c4: 4620 mov r0, r4
+ __HAL_FIREWALL_PREARM_ENABLE();
+ 80004c6: 6a1a ldr r2, [r3, #32]
+ 80004c8: f042 0201 orr.w r2, r2, #1
+ 80004cc: 621a str r2, [r3, #32]
+ 80004ce: 6a1b ldr r3, [r3, #32]
+ 80004d0: f003 0301 and.w r3, r3, #1
+ 80004d4: 930b str r3, [sp, #44] ; 0x2c
+ 80004d6: 9b0b ldr r3, [sp, #44] ; 0x2c
+}
+ 80004d8: b01e add sp, #120 ; 0x78
+ 80004da: bd70 pop {r4, r5, r6, pc}
+// Write bag number (probably a string)
+void flash_save_bag_number(const uint8_t new_number[32]);
+
+// Are we operating in level2?
+static inline bool flash_is_security_level2(void) {
+ rng_delay();
+ 80004dc: f002 f964 bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 80004e0: 4b5c ldr r3, [pc, #368] ; (8000654 <firewall_dispatch+0x2ac>)
+ 80004e2: 6a1b ldr r3, [r3, #32]
+ 80004e4: b2db uxtb r3, r3
+ 80004e6: f1a3 02cc sub.w r2, r3, #204 ; 0xcc
+ 80004ea: 4255 negs r5, r2
+ 80004ec: 4155 adcs r5, r2
+ switch(arg2) {
+ 80004ee: 9a01 ldr r2, [sp, #4]
+ 80004f0: 2a02 cmp r2, #2
+ 80004f2: d01c beq.n 800052e <firewall_dispatch+0x186>
+ 80004f4: 2a03 cmp r2, #3
+ 80004f6: d01f beq.n 8000538 <firewall_dispatch+0x190>
+ 80004f8: 2a01 cmp r2, #1
+ 80004fa: d013 beq.n 8000524 <firewall_dispatch+0x17c>
+ if(secure) {
+ 80004fc: 2bcc cmp r3, #204 ; 0xcc
+ 80004fe: f000 8216 beq.w 800092e <firewall_dispatch+0x586>
+ puts("Die: DFU");
+ 8000502: 4855 ldr r0, [pc, #340] ; (8000658 <firewall_dispatch+0x2b0>)
+ scr = screen_upgrading; // was screen_dfu, but limited audience
+ 8000504: 4c55 ldr r4, [pc, #340] ; (800065c <firewall_dispatch+0x2b4>)
+ puts("Die: DFU");
+ 8000506: f004 fc83 bl 8004e10 <puts>
+ bool secure = flash_is_security_level2();
+ 800050a: 2500 movs r5, #0
+ oled_setup();
+ 800050c: f000 fc0a bl 8000d24 <oled_setup>
+ oled_show(scr);
+ 8000510: 4620 mov r0, r4
+ 8000512: f000 fca5 bl 8000e60 <oled_show>
+ wipe_all_sram();
+ 8000516: f000 fa77 bl 8000a08 <wipe_all_sram>
+ psram_wipe();
+ 800051a: f004 fda1 bl 8005060 <psram_wipe>
+ if(secure) {
+ 800051e: b18d cbz r5, 8000544 <firewall_dispatch+0x19c>
+ LOCKUP_FOREVER();
+ 8000520: bf30 wfi
+ 8000522: e7fd b.n 8000520 <firewall_dispatch+0x178>
+ puts("Die: Downgrade");
+ 8000524: 484e ldr r0, [pc, #312] ; (8000660 <firewall_dispatch+0x2b8>)
+ scr = screen_downgrade;
+ 8000526: 4c4f ldr r4, [pc, #316] ; (8000664 <firewall_dispatch+0x2bc>)
+ puts("Die: Downgrade");
+ 8000528: f004 fc72 bl 8004e10 <puts>
+ break;
+ 800052c: e7ee b.n 800050c <firewall_dispatch+0x164>
+ puts("Die: Blankish");
+ 800052e: 484e ldr r0, [pc, #312] ; (8000668 <firewall_dispatch+0x2c0>)
+ scr = screen_blankish;
+ 8000530: 4c4e ldr r4, [pc, #312] ; (800066c <firewall_dispatch+0x2c4>)
+ puts("Die: Blankish");
+ 8000532: f004 fc6d bl 8004e10 <puts>
+ break;
+ 8000536: e7e9 b.n 800050c <firewall_dispatch+0x164>
+ puts("Die: Brick");
+ 8000538: 484d ldr r0, [pc, #308] ; (8000670 <firewall_dispatch+0x2c8>)
+ scr = screen_brick;
+ 800053a: 4c4e ldr r4, [pc, #312] ; (8000674 <firewall_dispatch+0x2cc>)
+ puts("Die: Brick");
+ 800053c: f004 fc68 bl 8004e10 <puts>
+ secure = true; // no point going into DFU, if even possible
+ 8000540: 2501 movs r5, #1
+ break;
+ 8000542: e7e3 b.n 800050c <firewall_dispatch+0x164>
+ memcpy(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic));
+ 8000544: 494c ldr r1, [pc, #304] ; (8000678 <firewall_dispatch+0x2d0>)
+ 8000546: 4a4d ldr r2, [pc, #308] ; (800067c <firewall_dispatch+0x2d4>)
+ 8000548: 6808 ldr r0, [r1, #0]
+ 800054a: 6849 ldr r1, [r1, #4]
+ 800054c: 4613 mov r3, r2
+ 800054e: c303 stmia r3!, {r0, r1}
+ dfu_flag->screen = scr;
+ 8000550: 6094 str r4, [r2, #8]
+ NVIC_SystemReset();
+ 8000552: f7ff fef7 bl 8000344 <__NVIC_SystemReset>
+ switch(arg2) {
+ 8000556: 9b01 ldr r3, [sp, #4]
+ 8000558: f033 0302 bics.w r3, r3, #2
+ 800055c: d102 bne.n 8000564 <firewall_dispatch+0x1bc>
+ oled_show(screen_logout);
+ 800055e: 4848 ldr r0, [pc, #288] ; (8000680 <firewall_dispatch+0x2d8>)
+ 8000560: f000 fc7e bl 8000e60 <oled_show>
+ wipe_all_sram();
+ 8000564: f000 fa50 bl 8000a08 <wipe_all_sram>
+ psram_wipe();
+ 8000568: f004 fd7a bl 8005060 <psram_wipe>
+ if(arg2 == 2) {
+ 800056c: 9b01 ldr r3, [sp, #4]
+ 800056e: 2b02 cmp r3, #2
+ 8000570: d103 bne.n 800057a <firewall_dispatch+0x1d2>
+ delay_ms(100);
+ 8000572: 2064 movs r0, #100 ; 0x64
+ 8000574: f003 f9d6 bl 8003924 <delay_ms>
+ 8000578: e7eb b.n 8000552 <firewall_dispatch+0x1aa>
+ LOCKUP_FOREVER();
+ 800057a: bf30 wfi
+ 800057c: e7fd b.n 800057a <firewall_dispatch+0x1d2>
+ ae_setup();
+ 800057e: f002 fa37 bl 80029f0 <ae_setup>
+ ae_keep_alive();
+ 8000582: f002 fa67 bl 8002a54 <ae_keep_alive>
+ switch(arg2) {
+ 8000586: 9b01 ldr r3, [sp, #4]
+ 8000588: 2b02 cmp r3, #2
+ 800058a: d00a beq.n 80005a2 <firewall_dispatch+0x1fa>
+ 800058c: 2b03 cmp r3, #3
+ 800058e: d00a beq.n 80005a6 <firewall_dispatch+0x1fe>
+ 8000590: 2b01 cmp r3, #1
+ 8000592: d002 beq.n 800059a <firewall_dispatch+0x1f2>
+ rv = ae_get_gpio();
+ 8000594: f002 ffdc bl 8003550 <ae_get_gpio>
+ 8000598: e752 b.n 8000440 <firewall_dispatch+0x98>
+ rv = ae_set_gpio(0);
+ 800059a: 2000 movs r0, #0
+ rv = ae_set_gpio(1);
+ 800059c: f002 ffaa bl 80034f4 <ae_set_gpio>
+ 80005a0: e74e b.n 8000440 <firewall_dispatch+0x98>
+ 80005a2: 2001 movs r0, #1
+ 80005a4: e7fa b.n 800059c <firewall_dispatch+0x1f4>
+ checksum_flash(fw_digest, world_digest, 0);
+ 80005a6: 2200 movs r2, #0
+ 80005a8: a90b add r1, sp, #44 ; 0x2c
+ 80005aa: a803 add r0, sp, #12
+ 80005ac: f001 fa5a bl 8001a64 <checksum_flash>
+ rv = ae_set_gpio_secure(world_digest);
+ 80005b0: a80b add r0, sp, #44 ; 0x2c
+ 80005b2: f002 ffb5 bl 8003520 <ae_set_gpio_secure>
+ 80005b6: 4604 mov r4, r0
+ oled_show(screen_blankish);
+ 80005b8: 482c ldr r0, [pc, #176] ; (800066c <firewall_dispatch+0x2c4>)
+ 80005ba: f000 fc51 bl 8000e60 <oled_show>
+ break;
+ 80005be: e75c b.n 800047a <firewall_dispatch+0xd2>
+ ae_setup();
+ 80005c0: f002 fa16 bl 80029f0 <ae_setup>
+ rv = (ae_pair_unlock() != 0);
+ 80005c4: f002 fc0a bl 8002ddc <ae_pair_unlock>
+ 80005c8: 1e04 subs r4, r0, #0
+ 80005ca: bf18 it ne
+ 80005cc: 2401 movne r4, #1
+ break;
+ 80005ce: e754 b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(1);
+ 80005d0: 2300 movs r3, #0
+ 80005d2: 2101 movs r1, #1
+ 80005d4: 4628 mov r0, r5
+ 80005d6: f7ff fec7 bl 8000368 <good_addr>
+ 80005da: 4604 mov r4, r0
+ 80005dc: 2800 cmp r0, #0
+ 80005de: f47f af4c bne.w 800047a <firewall_dispatch+0xd2>
+ buf_io[0] = 0; // NOT SUPPORTED on Mk4
+ 80005e2: 7028 strb r0, [r5, #0]
+ break;
+ 80005e4: e749 b.n 800047a <firewall_dispatch+0xd2>
+ if(len_in != 4 && len_in != 32 && len_in != 72) {
+ 80005e6: 2a04 cmp r2, #4
+ 80005e8: d004 beq.n 80005f4 <firewall_dispatch+0x24c>
+ 80005ea: 2a20 cmp r2, #32
+ 80005ec: d002 beq.n 80005f4 <firewall_dispatch+0x24c>
+ 80005ee: 2a48 cmp r2, #72 ; 0x48
+ 80005f0: f040 81d1 bne.w 8000996 <firewall_dispatch+0x5ee>
+ REQUIRE_OUT(4);
+ 80005f4: 2300 movs r3, #0
+ 80005f6: 2104 movs r1, #4
+ 80005f8: 4628 mov r0, r5
+ 80005fa: 9200 str r2, [sp, #0]
+ 80005fc: f7ff feb4 bl 8000368 <good_addr>
+ 8000600: 4604 mov r4, r0
+ 8000602: 2800 cmp r0, #0
+ 8000604: f47f af39 bne.w 800047a <firewall_dispatch+0xd2>
+ ae_setup();
+ 8000608: f002 f9f2 bl 80029f0 <ae_setup>
+ if(ae_read_data_slot(arg2 & 0xf, buf_io, len_in)) {
+ 800060c: 9801 ldr r0, [sp, #4]
+ 800060e: 9a00 ldr r2, [sp, #0]
+ 8000610: 4629 mov r1, r5
+ 8000612: f000 000f and.w r0, r0, #15
+ 8000616: f002 ff27 bl 8003468 <ae_read_data_slot>
+ if(rv) {
+ 800061a: 2800 cmp r0, #0
+ 800061c: f000 80d1 beq.w 80007c2 <firewall_dispatch+0x41a>
+ rv = EIO;
+ 8000620: 2405 movs r4, #5
+ 8000622: e72a b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(MAX_PIN_LEN);
+ 8000624: 2300 movs r3, #0
+ 8000626: 2120 movs r1, #32
+ 8000628: 4628 mov r0, r5
+ 800062a: f7ff fe9d bl 8000368 <good_addr>
+ 800062e: 4604 mov r4, r0
+ 8000630: 2800 cmp r0, #0
+ 8000632: f47f af22 bne.w 800047a <firewall_dispatch+0xd2>
+ if((arg2 < 1) || (arg2 > MAX_PIN_LEN)) {
+ 8000636: 9901 ldr r1, [sp, #4]
+ 8000638: 1e4b subs r3, r1, #1
+ 800063a: 2b1f cmp r3, #31
+ 800063c: f200 81ab bhi.w 8000996 <firewall_dispatch+0x5ee>
+ if(pin_prefix_words((char *)buf_io, arg2, (uint32_t *)buf_io)) {
+ 8000640: 462a mov r2, r5
+ 8000642: 4628 mov r0, r5
+ 8000644: f003 fc8e bl 8003f64 <pin_prefix_words>
+ 8000648: e7e7 b.n 800061a <firewall_dispatch+0x272>
+ 800064a: bf00 nop
+ 800064c: 40011c00 .word 0x40011c00
+ 8000650: 0800e7a8 .word 0x0800e7a8
+ 8000654: 40022000 .word 0x40022000
+ 8000658: 0800d766 .word 0x0800d766
+ 800065c: 0800e211 .word 0x0800e211
+ 8000660: 0800d76f .word 0x0800d76f
+ 8000664: 0800db00 .word 0x0800db00
+ 8000668: 0800d77e .word 0x0800d77e
+ 800066c: 0800d864 .word 0x0800d864
+ 8000670: 0800d78c .word 0x0800d78c
+ 8000674: 0800d891 .word 0x0800d891
+ 8000678: 0800d797 .word 0x0800d797
+ 800067c: 20008000 .word 0x20008000
+ 8000680: 0800dc1c .word 0x0800dc1c
+ REQUIRE_OUT(32);
+ 8000684: 2300 movs r3, #0
+ 8000686: 2120 movs r1, #32
+ 8000688: 4628 mov r0, r5
+ 800068a: f7ff fe6d bl 8000368 <good_addr>
+ 800068e: 4604 mov r4, r0
+ 8000690: 2800 cmp r0, #0
+ 8000692: f47f aef2 bne.w 800047a <firewall_dispatch+0xd2>
+ memset(buf_io, 0x55, 32); // to help show errors
+ 8000696: 2220 movs r2, #32
+ 8000698: 2155 movs r1, #85 ; 0x55
+ 800069a: 4628 mov r0, r5
+ 800069c: f00d f81c bl 800d6d8 <memset>
+ rng_buffer(buf_io, 32);
+ 80006a0: 2120 movs r1, #32
+ 80006a2: 4628 mov r0, r5
+ 80006a4: f002 f86a bl 800277c <rng_buffer>
+ break;
+ 80006a8: e6e7 b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(PIN_ATTEMPT_SIZE_V2);
+ 80006aa: 2300 movs r3, #0
+ 80006ac: f44f 718c mov.w r1, #280 ; 0x118
+ 80006b0: 4628 mov r0, r5
+ 80006b2: 9200 str r2, [sp, #0]
+ 80006b4: f7ff fe58 bl 8000368 <good_addr>
+ 80006b8: 4604 mov r4, r0
+ 80006ba: 2800 cmp r0, #0
+ 80006bc: f47f aedd bne.w 800047a <firewall_dispatch+0xd2>
+ switch(arg2) {
+ 80006c0: e9dd 2300 ldrd r2, r3, [sp]
+ 80006c4: 2b08 cmp r3, #8
+ 80006c6: d83d bhi.n 8000744 <firewall_dispatch+0x39c>
+ 80006c8: e8df f003 tbb [pc, r3]
+ 80006cc: 110d0905 .word 0x110d0905
+ 80006d0: 221d1915 .word 0x221d1915
+ 80006d4: 26 .byte 0x26
+ 80006d5: 00 .byte 0x00
+ rv = pin_setup_attempt(args);
+ 80006d6: 4628 mov r0, r5
+ 80006d8: f003 fc62 bl 8003fa0 <pin_setup_attempt>
+ 80006dc: e6b0 b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_delay(args);
+ 80006de: 4628 mov r0, r5
+ 80006e0: f003 fccc bl 800407c <pin_delay>
+ 80006e4: e6ac b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_login_attempt(args);
+ 80006e6: 4628 mov r0, r5
+ 80006e8: f003 fcca bl 8004080 <pin_login_attempt>
+ 80006ec: e6a8 b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_change(args);
+ 80006ee: 4628 mov r0, r5
+ 80006f0: f003 fdd4 bl 800429c <pin_change>
+ 80006f4: e6a4 b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_fetch_secret(args);
+ 80006f6: 4628 mov r0, r5
+ 80006f8: f003 fe88 bl 800440c <pin_fetch_secret>
+ 80006fc: e6a0 b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_firmware_greenlight(args);
+ 80006fe: 4628 mov r0, r5
+ 8000700: f004 f844 bl 800478c <pin_firmware_greenlight>
+ 8000704: e69c b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_long_secret(args, NULL);
+ 8000706: 2100 movs r1, #0
+ rv = pin_long_secret(args, &buf_io[PIN_ATTEMPT_SIZE_V2]);
+ 8000708: 4628 mov r0, r5
+ 800070a: f003 ff81 bl 8004610 <pin_long_secret>
+ 800070e: e697 b.n 8000440 <firewall_dispatch+0x98>
+ rv = pin_firmware_upgrade(args);
+ 8000710: 4628 mov r0, r5
+ 8000712: f004 f87b bl 800480c <pin_firmware_upgrade>
+ 8000716: e693 b.n 8000440 <firewall_dispatch+0x98>
+ REQUIRE_OUT(PIN_ATTEMPT_SIZE_V2 + AE_LONG_SECRET_LEN);
+ 8000718: 2300 movs r3, #0
+ 800071a: f44f 712e mov.w r1, #696 ; 0x2b8
+ 800071e: 4628 mov r0, r5
+ 8000720: f7ff fe22 bl 8000368 <good_addr>
+ 8000724: 4604 mov r4, r0
+ 8000726: 2800 cmp r0, #0
+ 8000728: f47f aea7 bne.w 800047a <firewall_dispatch+0xd2>
+ rv = pin_long_secret(args, &buf_io[PIN_ATTEMPT_SIZE_V2]);
+ 800072c: f505 718c add.w r1, r5, #280 ; 0x118
+ 8000730: e7ea b.n 8000708 <firewall_dispatch+0x360>
+ switch(arg2) {
+ 8000732: 9b01 ldr r3, [sp, #4]
+ 8000734: 2b64 cmp r3, #100 ; 0x64
+ 8000736: d041 beq.n 80007bc <firewall_dispatch+0x414>
+ 8000738: d806 bhi.n 8000748 <firewall_dispatch+0x3a0>
+ 800073a: 2b01 cmp r3, #1
+ 800073c: d01e beq.n 800077c <firewall_dispatch+0x3d4>
+ 800073e: 2b02 cmp r3, #2
+ 8000740: d028 beq.n 8000794 <firewall_dispatch+0x3ec>
+ 8000742: b13b cbz r3, 8000754 <firewall_dispatch+0x3ac>
+ 8000744: 2402 movs r4, #2
+ 8000746: e698 b.n 800047a <firewall_dispatch+0xd2>
+ 8000748: 2b65 cmp r3, #101 ; 0x65
+ 800074a: d03c beq.n 80007c6 <firewall_dispatch+0x41e>
+ 800074c: 2b66 cmp r3, #102 ; 0x66
+ 800074e: d1f9 bne.n 8000744 <firewall_dispatch+0x39c>
+ flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this.
+ 8000750: 20cc movs r0, #204 ; 0xcc
+ 8000752: e034 b.n 80007be <firewall_dispatch+0x416>
+ REQUIRE_OUT(32);
+ 8000754: 2120 movs r1, #32
+ 8000756: 4628 mov r0, r5
+ 8000758: f7ff fe06 bl 8000368 <good_addr>
+ 800075c: 4604 mov r4, r0
+ 800075e: 2800 cmp r0, #0
+ 8000760: f47f ae8b bne.w 800047a <firewall_dispatch+0xd2>
+ memcpy(buf_io, rom_secrets->bag_number, 32);
+ 8000764: 4aa1 ldr r2, [pc, #644] ; (80009ec <firewall_dispatch+0x644>)
+ 8000766: 4ea2 ldr r6, [pc, #648] ; (80009f0 <firewall_dispatch+0x648>)
+ 8000768: 4613 mov r3, r2
+ 800076a: cb03 ldmia r3!, {r0, r1}
+ 800076c: 42b3 cmp r3, r6
+ 800076e: 6028 str r0, [r5, #0]
+ 8000770: 6069 str r1, [r5, #4]
+ 8000772: 461a mov r2, r3
+ 8000774: f105 0508 add.w r5, r5, #8
+ 8000778: d1f6 bne.n 8000768 <firewall_dispatch+0x3c0>
+ 800077a: e67e b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_IN_ONLY(32);
+ 800077c: 2120 movs r1, #32
+ 800077e: 4628 mov r0, r5
+ 8000780: f7ff fdf2 bl 8000368 <good_addr>
+ 8000784: 4604 mov r4, r0
+ 8000786: 2800 cmp r0, #0
+ 8000788: f47f ae77 bne.w 800047a <firewall_dispatch+0xd2>
+ flash_save_bag_number(buf_io);
+ 800078c: 4628 mov r0, r5
+ 800078e: f001 fd0f bl 80021b0 <flash_save_bag_number>
+ break;
+ 8000792: e672 b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(1);
+ 8000794: 2300 movs r3, #0
+ 8000796: 2101 movs r1, #1
+ 8000798: 4628 mov r0, r5
+ 800079a: f7ff fde5 bl 8000368 <good_addr>
+ 800079e: 4604 mov r4, r0
+ 80007a0: 2800 cmp r0, #0
+ 80007a2: f47f ae6a bne.w 800047a <firewall_dispatch+0xd2>
+ rng_delay();
+ 80007a6: f001 ffff bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 80007aa: 4b92 ldr r3, [pc, #584] ; (80009f4 <firewall_dispatch+0x64c>)
+ 80007ac: 6a1b ldr r3, [r3, #32]
+ 80007ae: b2db uxtb r3, r3
+ buf_io[0] = (flash_is_security_level2() ? 2 : 0xff);
+ 80007b0: 2bcc cmp r3, #204 ; 0xcc
+ 80007b2: bf0c ite eq
+ 80007b4: 2302 moveq r3, #2
+ 80007b6: 23ff movne r3, #255 ; 0xff
+ buf_io[0] = 32;
+ 80007b8: 702b strb r3, [r5, #0]
+ break;
+ 80007ba: e65e b.n 800047a <firewall_dispatch+0xd2>
+ flash_lockdown_hard(OB_RDP_LEVEL_0); // wipes contents of flash (1->0)
+ 80007bc: 20aa movs r0, #170 ; 0xaa
+ flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this.
+ 80007be: f001 fdf9 bl 80023b4 <flash_lockdown_hard>
+ int rv = 0;
+ 80007c2: 2400 movs r4, #0
+ break;
+ 80007c4: e659 b.n 800047a <firewall_dispatch+0xd2>
+ flash_lockdown_hard(OB_RDP_LEVEL_1); // Can only do 0->1 (experiments)
+ 80007c6: 20bb movs r0, #187 ; 0xbb
+ 80007c8: e7f9 b.n 80007be <firewall_dispatch+0x416>
+ REQUIRE_OUT(128);
+ 80007ca: 2300 movs r3, #0
+ 80007cc: 2180 movs r1, #128 ; 0x80
+ 80007ce: 4628 mov r0, r5
+ 80007d0: f7ff fdca bl 8000368 <good_addr>
+ 80007d4: 4604 mov r4, r0
+ 80007d6: 2800 cmp r0, #0
+ 80007d8: f47f ae4f bne.w 800047a <firewall_dispatch+0xd2>
+ ae_setup();
+ 80007dc: f002 f908 bl 80029f0 <ae_setup>
+ rv = ae_config_read(buf_io);
+ 80007e0: 4628 mov r0, r5
+ 80007e2: f002 ff06 bl 80035f2 <ae_config_read>
+ 80007e6: e718 b.n 800061a <firewall_dispatch+0x272>
+ switch(arg2) {
+ 80007e8: 9b01 ldr r3, [sp, #4]
+ 80007ea: 2b03 cmp r3, #3
+ 80007ec: d8aa bhi.n 8000744 <firewall_dispatch+0x39c>
+ 80007ee: e8df f003 tbb [pc, r3]
+ 80007f2: 0f02 .short 0x0f02
+ 80007f4: 441d .short 0x441d
+ REQUIRE_OUT(8);
+ 80007f6: 2300 movs r3, #0
+ 80007f8: 2108 movs r1, #8
+ 80007fa: 4628 mov r0, r5
+ 80007fc: f7ff fdb4 bl 8000368 <good_addr>
+ 8000800: 4604 mov r4, r0
+ 8000802: 2800 cmp r0, #0
+ 8000804: f47f ae39 bne.w 800047a <firewall_dispatch+0xd2>
+ get_min_version(buf_io);
+ 8000808: 4628 mov r0, r5
+ 800080a: f001 f9bb bl 8001b84 <get_min_version>
+ break;
+ 800080e: e634 b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_IN_ONLY(8);
+ 8000810: 2301 movs r3, #1
+ 8000812: 2108 movs r1, #8
+ 8000814: 4628 mov r0, r5
+ 8000816: f7ff fda7 bl 8000368 <good_addr>
+ 800081a: 4604 mov r4, r0
+ 800081c: 2800 cmp r0, #0
+ 800081e: f47f ae2c bne.w 800047a <firewall_dispatch+0xd2>
+ rv = check_is_downgrade(buf_io, NULL);
+ 8000822: 4601 mov r1, r0
+ 8000824: 4628 mov r0, r5
+ 8000826: f001 f9cd bl 8001bc4 <check_is_downgrade>
+ 800082a: e609 b.n 8000440 <firewall_dispatch+0x98>
+ REQUIRE_IN_ONLY(8);
+ 800082c: 2301 movs r3, #1
+ 800082e: 2108 movs r1, #8
+ 8000830: 4628 mov r0, r5
+ 8000832: f7ff fd99 bl 8000368 <good_addr>
+ 8000836: 4604 mov r4, r0
+ 8000838: 2800 cmp r0, #0
+ 800083a: f47f ae1e bne.w 800047a <firewall_dispatch+0xd2>
+ if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) {
+ 800083e: 782b ldrb r3, [r5, #0]
+ 8000840: 3b10 subs r3, #16
+ rv = ERANGE;
+ 8000842: 2b2f cmp r3, #47 ; 0x2f
+ } if(check_is_downgrade(buf_io, NULL)) {
+ 8000844: 4601 mov r1, r0
+ 8000846: 4628 mov r0, r5
+ rv = ERANGE;
+ 8000848: bf88 it hi
+ 800084a: 2422 movhi r4, #34 ; 0x22
+ } if(check_is_downgrade(buf_io, NULL)) {
+ 800084c: f001 f9ba bl 8001bc4 <check_is_downgrade>
+ 8000850: 2800 cmp r0, #0
+ 8000852: f040 80c8 bne.w 80009e6 <firewall_dispatch+0x63e>
+ get_min_version(min);
+ 8000856: a80b add r0, sp, #44 ; 0x2c
+ 8000858: f001 f994 bl 8001b84 <get_min_version>
+ if(memcmp(min, buf_io, 8) == 0) {
+ 800085c: 2208 movs r2, #8
+ 800085e: 4629 mov r1, r5
+ 8000860: a80b add r0, sp, #44 ; 0x2c
+ 8000862: f00c ff01 bl 800d668 <memcmp>
+ 8000866: 2800 cmp r0, #0
+ 8000868: f000 80bd beq.w 80009e6 <firewall_dispatch+0x63e>
+ if(record_highwater_version(buf_io)) {
+ 800086c: 4628 mov r0, r5
+ 800086e: f001 fdbb bl 80023e8 <record_highwater_version>
+ rv = ENOMEM;
+ 8000872: 2800 cmp r0, #0
+ 8000874: bf18 it ne
+ 8000876: 240c movne r4, #12
+ 8000878: e5ff b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(4);
+ 800087a: 2300 movs r3, #0
+ 800087c: 2104 movs r1, #4
+ 800087e: 4628 mov r0, r5
+ 8000880: f7ff fd72 bl 8000368 <good_addr>
+ 8000884: 4604 mov r4, r0
+ 8000886: 2800 cmp r0, #0
+ 8000888: f47f adf7 bne.w 800047a <firewall_dispatch+0xd2>
+ ae_setup();
+ 800088c: f002 f8b0 bl 80029f0 <ae_setup>
+ rv = ae_get_counter((uint32_t *)buf_io, 0) ? EIO: 0;
+ 8000890: 4621 mov r1, r4
+ 8000892: 4628 mov r0, r5
+ 8000894: f002 fc9d bl 80031d2 <ae_get_counter>
+ 8000898: e6bf b.n 800061a <firewall_dispatch+0x272>
+ REQUIRE_OUT(PIN_ATTEMPT_SIZE_V2 + sizeof(trick_slot_t));
+ 800089a: 2300 movs r3, #0
+ 800089c: f44f 71cc mov.w r1, #408 ; 0x198
+ 80008a0: 4628 mov r0, r5
+ 80008a2: f7ff fd61 bl 8000368 <good_addr>
+ 80008a6: 4604 mov r4, r0
+ 80008a8: 2800 cmp r0, #0
+ 80008aa: f47f ade6 bne.w 800047a <firewall_dispatch+0xd2>
+ rv = pin_check_logged_in(args, &trick_mode);
+ 80008ae: a90b add r1, sp, #44 ; 0x2c
+ 80008b0: 4628 mov r0, r5
+ 80008b2: f003 fcc1 bl 8004238 <pin_check_logged_in>
+ if(rv) goto fail;
+ 80008b6: 4604 mov r4, r0
+ 80008b8: 2800 cmp r0, #0
+ 80008ba: f47f adde bne.w 800047a <firewall_dispatch+0xd2>
+ if(trick_mode) {
+ 80008be: f89d 302c ldrb.w r3, [sp, #44] ; 0x2c
+ 80008c2: b10b cbz r3, 80008c8 <firewall_dispatch+0x520>
+ mcu_key_clear(NULL);
+ 80008c4: f001 fdde bl 8002484 <mcu_key_clear>
+ switch(arg2) {
+ 80008c8: 9b01 ldr r3, [sp, #4]
+ 80008ca: 2b01 cmp r3, #1
+ trick_slot_t *slot = (trick_slot_t *)(&buf_io[PIN_ATTEMPT_SIZE_V2]);
+ 80008cc: f505 728c add.w r2, r5, #280 ; 0x118
+ switch(arg2) {
+ 80008d0: d00c beq.n 80008ec <firewall_dispatch+0x544>
+ 80008d2: 2b02 cmp r3, #2
+ 80008d4: d01b beq.n 800090e <firewall_dispatch+0x566>
+ 80008d6: 2b00 cmp r3, #0
+ 80008d8: f47f af34 bne.w 8000744 <firewall_dispatch+0x39c>
+ if(!trick_mode) {
+ 80008dc: f89d 302c ldrb.w r3, [sp, #44] ; 0x2c
+ 80008e0: 2b00 cmp r3, #0
+ 80008e2: f47f adca bne.w 800047a <firewall_dispatch+0xd2>
+ se2_clear_tricks();
+ 80008e6: f007 fa63 bl 8007db0 <se2_clear_tricks>
+ 80008ea: e5c6 b.n 800047a <firewall_dispatch+0xd2>
+ if(trick_mode) {
+ 80008ec: f89d 102c ldrb.w r1, [sp, #44] ; 0x2c
+ 80008f0: 2900 cmp r1, #0
+ 80008f2: f47f af27 bne.w 8000744 <firewall_dispatch+0x39c>
+ if(slot->pin_len > 16) {
+ 80008f6: f8d5 1170 ldr.w r1, [r5, #368] ; 0x170
+ 80008fa: 2910 cmp r1, #16
+ 80008fc: dc4b bgt.n 8000996 <firewall_dispatch+0x5ee>
+ if(se2_test_trick_pin(slot->pin, slot->pin_len, slot, true)) {
+ 80008fe: f505 70b0 add.w r0, r5, #352 ; 0x160
+ 8000902: f007 fabb bl 8007e7c <se2_test_trick_pin>
+ 8000906: 2800 cmp r0, #0
+ 8000908: f47f adb7 bne.w 800047a <firewall_dispatch+0xd2>
+ 800090c: e71a b.n 8000744 <firewall_dispatch+0x39c>
+ if(!trick_mode) {
+ 800090e: f89d 302c ldrb.w r3, [sp, #44] ; 0x2c
+ 8000912: 2b00 cmp r3, #0
+ 8000914: f47f adb1 bne.w 800047a <firewall_dispatch+0xd2>
+ rv = se2_save_trick(slot);
+ 8000918: 4610 mov r0, r2
+ 800091a: f007 fbcf bl 80080bc <se2_save_trick>
+ 800091e: e58f b.n 8000440 <firewall_dispatch+0x98>
+ if(arg2 == 0xBeef) {
+ 8000920: 9b01 ldr r3, [sp, #4]
+ 8000922: f64b 62ef movw r2, #48879 ; 0xbeef
+ 8000926: 4293 cmp r3, r2
+ 8000928: d103 bne.n 8000932 <firewall_dispatch+0x58a>
+ fast_wipe();
+ 800092a: f001 fe9d bl 8002668 <fast_wipe>
+ rv = EPERM;
+ 800092e: 2401 movs r4, #1
+ 8000930: e5a3 b.n 800047a <firewall_dispatch+0xd2>
+ } else if(arg2 == 0xDead) {
+ 8000932: f64d 62ad movw r2, #57005 ; 0xdead
+ 8000936: 4293 cmp r3, r2
+ 8000938: d1f9 bne.n 800092e <firewall_dispatch+0x586>
+ mcu_key_clear(NULL);
+ 800093a: 2000 movs r0, #0
+ 800093c: f001 fda2 bl 8002484 <mcu_key_clear>
+ oled_show(screen_wiped);
+ 8000940: 482d ldr r0, [pc, #180] ; (80009f8 <firewall_dispatch+0x650>)
+ 8000942: f000 fa8d bl 8000e60 <oled_show>
+ LOCKUP_FOREVER();
+ 8000946: bf30 wfi
+ 8000948: e7fd b.n 8000946 <firewall_dispatch+0x59e>
+ if(arg2 == 0xDead) fast_brick();
+ 800094a: 9a01 ldr r2, [sp, #4]
+ 800094c: f64d 63ad movw r3, #57005 ; 0xdead
+ 8000950: 429a cmp r2, r3
+ 8000952: d1ec bne.n 800092e <firewall_dispatch+0x586>
+ 8000954: f001 fe5a bl 800260c <fast_brick>
+ 8000958: e7e9 b.n 800092e <firewall_dispatch+0x586>
+ REQUIRE_OUT(8);
+ 800095a: 2300 movs r3, #0
+ 800095c: 2108 movs r1, #8
+ 800095e: 4628 mov r0, r5
+ 8000960: f7ff fd02 bl 8000368 <good_addr>
+ 8000964: 4604 mov r4, r0
+ 8000966: 2800 cmp r0, #0
+ 8000968: f47f ad87 bne.w 800047a <firewall_dispatch+0xd2>
+ mcu_key_usage(avail, consumed, total);
+ 800096c: f105 0208 add.w r2, r5, #8
+ 8000970: 1d29 adds r1, r5, #4
+ 8000972: 4628 mov r0, r5
+ 8000974: f001 fdb4 bl 80024e0 <mcu_key_usage>
+ break;
+ 8000978: e57f b.n 800047a <firewall_dispatch+0xd2>
+ REQUIRE_OUT(33);
+ 800097a: 2300 movs r3, #0
+ 800097c: 2121 movs r1, #33 ; 0x21
+ 800097e: 4628 mov r0, r5
+ 8000980: f7ff fcf2 bl 8000368 <good_addr>
+ 8000984: 4604 mov r4, r0
+ 8000986: 2800 cmp r0, #0
+ 8000988: f47f ad77 bne.w 800047a <firewall_dispatch+0xd2>
+ switch(arg2) {
+ 800098c: 9b01 ldr r3, [sp, #4]
+ 800098e: 2b01 cmp r3, #1
+ 8000990: d003 beq.n 800099a <firewall_dispatch+0x5f2>
+ 8000992: 2b02 cmp r3, #2
+ 8000994: d008 beq.n 80009a8 <firewall_dispatch+0x600>
+ rv = ERANGE;
+ 8000996: 2422 movs r4, #34 ; 0x22
+ 8000998: e56f b.n 800047a <firewall_dispatch+0xd2>
+ ae_setup();
+ 800099a: f002 f829 bl 80029f0 <ae_setup>
+ ae_secure_random(&buf_io[1]);
+ 800099e: 1c68 adds r0, r5, #1
+ 80009a0: f002 fb8e bl 80030c0 <ae_secure_random>
+ buf_io[0] = 32;
+ 80009a4: 2320 movs r3, #32
+ 80009a6: e707 b.n 80007b8 <firewall_dispatch+0x410>
+ se2_read_rng(&buf_io[1]);
+ 80009a8: 1c68 adds r0, r5, #1
+ 80009aa: f007 fd6b bl 8008484 <se2_read_rng>
+ buf_io[0] = 8;
+ 80009ae: 2308 movs r3, #8
+ 80009b0: e702 b.n 80007b8 <firewall_dispatch+0x410>
+ REQUIRE_OUT(80);
+ 80009b2: 2300 movs r3, #0
+ 80009b4: 2150 movs r1, #80 ; 0x50
+ 80009b6: 4628 mov r0, r5
+ 80009b8: f7ff fcd6 bl 8000368 <good_addr>
+ 80009bc: 4604 mov r4, r0
+ 80009be: 2800 cmp r0, #0
+ 80009c0: f47f ad5b bne.w 800047a <firewall_dispatch+0xd2>
+ strcpy((char *)buf_io, "ATECC608B\nDS28C36B");
+ 80009c4: 490d ldr r1, [pc, #52] ; (80009fc <firewall_dispatch+0x654>)
+ 80009c6: 4628 mov r0, r5
+ 80009c8: f00c fe9c bl 800d704 <strcpy>
+ break;
+ 80009cc: e555 b.n 800047a <firewall_dispatch+0xd2>
+ if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) {
+ 80009ce: f1b4 6f00 cmp.w r4, #134217728 ; 0x8000000
+ 80009d2: d902 bls.n 80009da <firewall_dispatch+0x632>
+ 80009d4: 4b0a ldr r3, [pc, #40] ; (8000a00 <firewall_dispatch+0x658>)
+ 80009d6: 429c cmp r4, r3
+ 80009d8: d302 bcc.n 80009e0 <firewall_dispatch+0x638>
+ fatal_error("LR");
+ 80009da: 480a ldr r0, [pc, #40] ; (8000a04 <firewall_dispatch+0x65c>)
+ 80009dc: f000 f834 bl 8000a48 <fatal_error>
+ system_startup();
+ 80009e0: f000 f890 bl 8000b04 <system_startup>
+ break;
+ 80009e4: e6ed b.n 80007c2 <firewall_dispatch+0x41a>
+ rv = EAGAIN;
+ 80009e6: 240b movs r4, #11
+ 80009e8: e547 b.n 800047a <firewall_dispatch+0xd2>
+ 80009ea: bf00 nop
+ 80009ec: 0801c050 .word 0x0801c050
+ 80009f0: 0801c070 .word 0x0801c070
+ 80009f4: 40022000 .word 0x40022000
+ 80009f8: 0800e396 .word 0x0800e396
+ 80009fc: 0800d7a0 .word 0x0800d7a0
+ 8000a00: 08000300 .word 0x08000300
+ 8000a04: 0800d7b3 .word 0x0800d7b3
+
+08000a08 <wipe_all_sram>:
+//
+ static inline void
+memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
+{
+ for(; byte_len; byte_len-=4, dest++) {
+ *dest = value;
+ 8000a08: 4a0a ldr r2, [pc, #40] ; (8000a34 <wipe_all_sram+0x2c>)
+ for(; byte_len; byte_len-=4, dest++) {
+ 8000a0a: 490b ldr r1, [pc, #44] ; (8000a38 <wipe_all_sram+0x30>)
+
+// wipe_all_sram()
+//
+ void
+wipe_all_sram(void)
+{
+ 8000a0c: f04f 5300 mov.w r3, #536870912 ; 0x20000000
+ *dest = value;
+ 8000a10: f843 2b04 str.w r2, [r3], #4
+ for(; byte_len; byte_len-=4, dest++) {
+ 8000a14: 428b cmp r3, r1
+ 8000a16: d1fb bne.n 8000a10 <wipe_all_sram+0x8>
+ 8000a18: 4908 ldr r1, [pc, #32] ; (8000a3c <wipe_all_sram+0x34>)
+ 8000a1a: f04f 5380 mov.w r3, #268435456 ; 0x10000000
+ *dest = value;
+ 8000a1e: f843 2b04 str.w r2, [r3], #4
+ for(; byte_len; byte_len-=4, dest++) {
+ 8000a22: 428b cmp r3, r1
+ 8000a24: d1fb bne.n 8000a1e <wipe_all_sram+0x16>
+ 8000a26: 4b06 ldr r3, [pc, #24] ; (8000a40 <wipe_all_sram+0x38>)
+ 8000a28: 4906 ldr r1, [pc, #24] ; (8000a44 <wipe_all_sram+0x3c>)
+ *dest = value;
+ 8000a2a: f843 2b04 str.w r2, [r3], #4
+ for(; byte_len; byte_len-=4, dest++) {
+ 8000a2e: 428b cmp r3, r1
+ 8000a30: d1fb bne.n 8000a2a <wipe_all_sram+0x22>
+ STATIC_ASSERT((SRAM3_BASE + SRAM3_SIZE) - BL_SRAM_BASE == 8192);
+
+ memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX);
+ memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE);
+ memset4((void *)SRAM3_BASE, noise, SRAM3_SIZE - (BL_SRAM_BASE - SRAM3_BASE));
+}
+ 8000a32: 4770 bx lr
+ 8000a34: deadbeef .word 0xdeadbeef
+ 8000a38: 20030000 .word 0x20030000
+ 8000a3c: 10010000 .word 0x10010000
+ 8000a40: 20040000 .word 0x20040000
+ 8000a44: 20042000 .word 0x20042000
+
+08000a48 <fatal_error>:
+
+// fatal_error(const char *msg)
+//
+ void __attribute__((noreturn))
+fatal_error(const char *msgvoid)
+{
+ 8000a48: b508 push {r3, lr}
+ oled_setup();
+ 8000a4a: f000 f96b bl 8000d24 <oled_setup>
+ oled_show(screen_fatal);
+ 8000a4e: 4802 ldr r0, [pc, #8] ; (8000a58 <fatal_error+0x10>)
+ 8000a50: f000 fa06 bl 8000e60 <oled_show>
+ BREAKPOINT;
+#endif
+
+ // Maybe should do a reset after a delay, like with
+ // the watchdog timer or something.
+ LOCKUP_FOREVER();
+ 8000a54: bf30 wfi
+ 8000a56: e7fd b.n 8000a54 <fatal_error+0xc>
+ 8000a58: 0800dbd8 .word 0x0800dbd8
+
+08000a5c <fatal_mitm>:
+
+// fatal_mitm()
+//
+ void __attribute__((noreturn))
+fatal_mitm(void)
+{
+ 8000a5c: b508 push {r3, lr}
+ oled_setup();
+ 8000a5e: f000 f961 bl 8000d24 <oled_setup>
+ oled_show(screen_mitm);
+ 8000a62: 4803 ldr r0, [pc, #12] ; (8000a70 <fatal_mitm+0x14>)
+ 8000a64: f000 f9fc bl 8000e60 <oled_show>
+
+#ifdef RELEASE
+ wipe_all_sram();
+ 8000a68: f7ff ffce bl 8000a08 <wipe_all_sram>
+#endif
+
+ LOCKUP_FOREVER();
+ 8000a6c: bf30 wfi
+ 8000a6e: e7fd b.n 8000a6c <fatal_mitm+0x10>
+ 8000a70: 0800dcdc .word 0x0800dcdc
+
+08000a74 <enter_dfu>:
+
+// enter_dfu()
+//
+ void __attribute__((noreturn))
+enter_dfu(void)
+{
+ 8000a74: b507 push {r0, r1, r2, lr}
+ puts("enter_dfu()");
+ 8000a76: 481f ldr r0, [pc, #124] ; (8000af4 <enter_dfu+0x80>)
+ 8000a78: f004 f9ca bl 8004e10 <puts>
+
+ // clear the green light, if set
+ ae_setup();
+ 8000a7c: f001 ffb8 bl 80029f0 <ae_setup>
+ ae_set_gpio(0);
+ 8000a80: 2000 movs r0, #0
+ 8000a82: f002 fd37 bl 80034f4 <ae_set_gpio>
+
+ // Reset huge parts of the chip
+ __HAL_RCC_APB1_FORCE_RESET();
+ 8000a86: 4b1c ldr r3, [pc, #112] ; (8000af8 <enter_dfu+0x84>)
+ 8000a88: f04f 31ff mov.w r1, #4294967295 ; 0xffffffff
+ __HAL_RCC_APB1_RELEASE_RESET();
+ 8000a8c: 2200 movs r2, #0
+ __HAL_RCC_APB1_FORCE_RESET();
+ 8000a8e: 6399 str r1, [r3, #56] ; 0x38
+ 8000a90: 63d9 str r1, [r3, #60] ; 0x3c
+ __HAL_RCC_APB1_RELEASE_RESET();
+ 8000a92: 639a str r2, [r3, #56] ; 0x38
+ 8000a94: 63da str r2, [r3, #60] ; 0x3c
+
+ __HAL_RCC_APB2_FORCE_RESET();
+ 8000a96: 6419 str r1, [r3, #64] ; 0x40
+ __HAL_RCC_APB2_RELEASE_RESET();
+ 8000a98: 641a str r2, [r3, #64] ; 0x40
+
+ __HAL_RCC_AHB1_FORCE_RESET();
+ 8000a9a: 6299 str r1, [r3, #40] ; 0x28
+ __HAL_RCC_AHB1_RELEASE_RESET();
+ 8000a9c: 629a str r2, [r3, #40] ; 0x28
+ // But not this; it borks things.
+ __HAL_RCC_AHB2_FORCE_RESET();
+ __HAL_RCC_AHB2_RELEASE_RESET();
+#endif
+
+ __HAL_RCC_AHB3_FORCE_RESET();
+ 8000a9e: 6319 str r1, [r3, #48] ; 0x30
+ __HAL_RCC_AHB3_RELEASE_RESET();
+ 8000aa0: 631a str r2, [r3, #48] ; 0x30
+
+ __HAL_FIREWALL_PREARM_ENABLE();
+ 8000aa2: f5a3 4374 sub.w r3, r3, #62464 ; 0xf400
+ 8000aa6: 6a1a ldr r2, [r3, #32]
+ 8000aa8: f042 0201 orr.w r2, r2, #1
+ 8000aac: 621a str r2, [r3, #32]
+ 8000aae: 6a1b ldr r3, [r3, #32]
+ 8000ab0: f003 0301 and.w r3, r3, #1
+ 8000ab4: 9301 str r3, [sp, #4]
+ 8000ab6: 9b01 ldr r3, [sp, #4]
+
+ // Wipe all of memory SRAM, just in case
+ // there is some way to trick us into DFU
+ // after sensitive content in place.
+ wipe_all_sram();
+ 8000ab8: f7ff ffa6 bl 8000a08 <wipe_all_sram>
+ rng_delay();
+ 8000abc: f001 fe74 bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 8000ac0: 4b0e ldr r3, [pc, #56] ; (8000afc <enter_dfu+0x88>)
+ 8000ac2: 6a1b ldr r3, [r3, #32]
+ 8000ac4: b2db uxtb r3, r3
+
+ if(flash_is_security_level2()) {
+ 8000ac6: 2bcc cmp r3, #204 ; 0xcc
+ 8000ac8: d101 bne.n 8000ace <enter_dfu+0x5a>
+ // cannot do DFU in RDP=2, so just die. Helps to preserve screen
+ LOCKUP_FOREVER();
+ 8000aca: bf30 wfi
+ 8000acc: e7fd b.n 8000aca <enter_dfu+0x56>
+ }
+
+ // Reset clocks.
+ HAL_RCC_DeInit();
+ 8000ace: f007 fe17 bl 8008700 <HAL_RCC_DeInit>
+
+ // move system ROM into 0x0
+ __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
+ 8000ad2: 4a0b ldr r2, [pc, #44] ; (8000b00 <enter_dfu+0x8c>)
+ 8000ad4: 6813 ldr r3, [r2, #0]
+ 8000ad6: f023 0307 bic.w r3, r3, #7
+ 8000ada: f043 0301 orr.w r3, r3, #1
+ 8000ade: 6013 str r3, [r2, #0]
+
+ // need this here?!
+ asm("nop; nop; nop; nop;");
+ 8000ae0: bf00 nop
+ 8000ae2: bf00 nop
+ 8000ae4: bf00 nop
+ 8000ae6: bf00 nop
+
+ // simulate a reset vector
+ __ASM volatile ("movs r0, #0\n"
+ 8000ae8: 2000 movs r0, #0
+ 8000aea: 6803 ldr r3, [r0, #0]
+ 8000aec: f383 8808 msr MSP, r3
+ 8000af0: 6843 ldr r3, [r0, #4]
+ 8000af2: 4798 blx r3
+ "ldr r3, [r0, #4]\n"
+ "blx r3"
+ : : : "r0", "r3"); // also SP
+
+ // NOT-REACHED.
+ __builtin_unreachable();
+ 8000af4: 0800d7b6 .word 0x0800d7b6
+ 8000af8: 40021000 .word 0x40021000
+ 8000afc: 40022000 .word 0x40022000
+ 8000b00: 40010000 .word 0x40010000
+
+08000b04 <system_startup>:
+{
+ 8000b04: b510 push {r4, lr}
+ system_init0();
+ 8000b06: f001 f99b bl 8001e40 <system_init0>
+ clocks_setup();
+ 8000b0a: f001 f9bb bl 8001e84 <clocks_setup>
+ rng_setup(); // needs to be super early
+ 8000b0e: f001 fe09 bl 8002724 <rng_setup>
+ rng_delay();
+ 8000b12: f001 fe49 bl 80027a8 <rng_delay>
+ if(!check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))
+ 8000b16: 4838 ldr r0, [pc, #224] ; (8000bf8 <system_startup+0xf4>)
+ 8000b18: 2120 movs r1, #32
+ 8000b1a: f001 fdc7 bl 80026ac <check_all_ones>
+ 8000b1e: b948 cbnz r0, 8000b34 <system_startup+0x30>
+ rng_delay();
+ 8000b20: f001 fe42 bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 8000b24: 4b35 ldr r3, [pc, #212] ; (8000bfc <system_startup+0xf8>)
+ 8000b26: 6a1b ldr r3, [r3, #32]
+ 8000b28: b2db uxtb r3, r3
+ && !flash_is_security_level2()
+ 8000b2a: 2bcc cmp r3, #204 ; 0xcc
+ 8000b2c: d002 beq.n 8000b34 <system_startup+0x30>
+ flash_lockdown_hard(OB_RDP_LEVEL_2);
+ 8000b2e: 20cc movs r0, #204 ; 0xcc
+ 8000b30: f001 fc40 bl 80023b4 <flash_lockdown_hard>
+ gpio_setup();
+ 8000b34: f002 ff06 bl 8003944 <gpio_setup>
+ uint32_t reset_reason = RCC->CSR;
+ 8000b38: 4c31 ldr r4, [pc, #196] ; (8000c00 <system_startup+0xfc>)
+ console_setup();
+ 8000b3a: f004 f88f bl 8004c5c <console_setup>
+ puts2(BOOT_BANNER);
+ 8000b3e: 4831 ldr r0, [pc, #196] ; (8000c04 <system_startup+0x100>)
+ 8000b40: f004 f8d8 bl 8004cf4 <puts2>
+ puts(version_string);
+ 8000b44: 4830 ldr r0, [pc, #192] ; (8000c08 <system_startup+0x104>)
+ 8000b46: f004 f963 bl 8004e10 <puts>
+ uint32_t reset_reason = RCC->CSR;
+ 8000b4a: f8d4 3094 ldr.w r3, [r4, #148] ; 0x94
+ if(reset_reason & RCC_CSR_FWRSTF) {
+ 8000b4e: 01db lsls r3, r3, #7
+ 8000b50: d502 bpl.n 8000b58 <system_startup+0x54>
+ puts(">FIREWALLED<");
+ 8000b52: 482e ldr r0, [pc, #184] ; (8000c0c <system_startup+0x108>)
+ 8000b54: f004 f95c bl 8004e10 <puts>
+ SET_BIT(RCC->CSR, RCC_CSR_RMVF);
+ 8000b58: f8d4 3094 ldr.w r3, [r4, #148] ; 0x94
+ 8000b5c: f443 0300 orr.w r3, r3, #8388608 ; 0x800000
+ 8000b60: f8c4 3094 str.w r3, [r4, #148] ; 0x94
+ if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) {
+ 8000b64: 4c2a ldr r4, [pc, #168] ; (8000c10 <system_startup+0x10c>)
+ pin_setup0();
+ 8000b66: f003 f967 bl 8003e38 <pin_setup0>
+ rng_delay();
+ 8000b6a: f001 fe1d bl 80027a8 <rng_delay>
+ oled_setup();
+ 8000b6e: f000 f8d9 bl 8000d24 <oled_setup>
+ if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) {
+ 8000b72: 4928 ldr r1, [pc, #160] ; (8000c14 <system_startup+0x110>)
+ 8000b74: 2208 movs r2, #8
+ 8000b76: 4620 mov r0, r4
+ 8000b78: f00c fd76 bl 800d668 <memcmp>
+ 8000b7c: b928 cbnz r0, 8000b8a <system_startup+0x86>
+ dfu_flag->magic[0] = 0;
+ 8000b7e: 7020 strb r0, [r4, #0]
+ oled_show(dfu_flag->screen);
+ 8000b80: 68a0 ldr r0, [r4, #8]
+ 8000b82: f000 f96d bl 8000e60 <oled_show>
+ enter_dfu();
+ 8000b86: f7ff ff75 bl 8000a74 <enter_dfu>
+ rng_delay();
+ 8000b8a: f001 fe0d bl 80027a8 <rng_delay>
+ oled_show_progress(screen_verify, 0);
+ 8000b8e: 2100 movs r1, #0
+ 8000b90: 4821 ldr r0, [pc, #132] ; (8000c18 <system_startup+0x114>)
+ 8000b92: f000 f9a7 bl 8000ee4 <oled_show_progress>
+ wipe_all_sram();
+ 8000b96: f7ff ff37 bl 8000a08 <wipe_all_sram>
+ ae_setup();
+ 8000b9a: f001 ff29 bl 80029f0 <ae_setup>
+ ae_set_gpio(0); // turn light red
+ 8000b9e: 2000 movs r0, #0
+ 8000ba0: f002 fca8 bl 80034f4 <ae_set_gpio>
+ se2_setup();
+ 8000ba4: f007 f8be bl 8007d24 <se2_setup>
+ se2_probe();
+ 8000ba8: f006 fe42 bl 8007830 <se2_probe>
+ flash_setup();
+ 8000bac: f001 fb6c bl 8002288 <flash_setup>
+ psram_setup();
+ 8000bb0: f004 f966 bl 8004e80 <psram_setup>
+ if(ae_pair_unlock() != 0) {
+ 8000bb4: f002 f912 bl 8002ddc <ae_pair_unlock>
+ 8000bb8: b138 cbz r0, 8000bca <system_startup+0xc6>
+ oled_show(screen_brick);
+ 8000bba: 4818 ldr r0, [pc, #96] ; (8000c1c <system_startup+0x118>)
+ 8000bbc: f000 f950 bl 8000e60 <oled_show>
+ puts("pair-bricked");
+ 8000bc0: 4817 ldr r0, [pc, #92] ; (8000c20 <system_startup+0x11c>)
+ 8000bc2: f004 f925 bl 8004e10 <puts>
+ LOCKUP_FOREVER();
+ 8000bc6: bf30 wfi
+ 8000bc8: e7fd b.n 8000bc6 <system_startup+0xc2>
+ puts2("Verify: ");
+ 8000bca: 4816 ldr r0, [pc, #88] ; (8000c24 <system_startup+0x120>)
+ 8000bcc: f004 f892 bl 8004cf4 <puts2>
+ bool main_ok = verify_firmware();
+ 8000bd0: f001 f8ba bl 8001d48 <verify_firmware>
+ if(main_ok) {
+ 8000bd4: b120 cbz r0, 8000be0 <system_startup+0xdc>
+}
+ 8000bd6: e8bd 4010 ldmia.w sp!, {r4, lr}
+ oled_show(screen_blankish);
+ 8000bda: 4813 ldr r0, [pc, #76] ; (8000c28 <system_startup+0x124>)
+ 8000bdc: f000 b940 b.w 8000e60 <oled_show>
+ psram_recover_firmware();
+ 8000be0: f004 fa9c bl 800511c <psram_recover_firmware>
+ rng_delay();
+ 8000be4: f001 fde0 bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 8000be8: 4b04 ldr r3, [pc, #16] ; (8000bfc <system_startup+0xf8>)
+ 8000bea: 6a1b ldr r3, [r3, #32]
+ 8000bec: b2db uxtb r3, r3
+ if(!flash_is_security_level2()) {
+ 8000bee: 2bcc cmp r3, #204 ; 0xcc
+ 8000bf0: d1c9 bne.n 8000b86 <system_startup+0x82>
+ while(1) sdcard_recovery();
+ 8000bf2: f004 fc43 bl 800547c <sdcard_recovery>
+ 8000bf6: e7fc b.n 8000bf2 <system_startup+0xee>
+ 8000bf8: 0801c050 .word 0x0801c050
+ 8000bfc: 40022000 .word 0x40022000
+ 8000c00: 40021000 .word 0x40021000
+ 8000c04: 0800d7c2 .word 0x0800d7c2
+ 8000c08: 0800e7a8 .word 0x0800e7a8
+ 8000c0c: 0800d7d6 .word 0x0800d7d6
+ 8000c10: 20008000 .word 0x20008000
+ 8000c14: 0800d797 .word 0x0800d797
+ 8000c18: 0800e2c8 .word 0x0800e2c8
+ 8000c1c: 0800d891 .word 0x0800d891
+ 8000c20: 0800d7e3 .word 0x0800d7e3
+ 8000c24: 0800d7f0 .word 0x0800d7f0
+ 8000c28: 0800d864 .word 0x0800d864
+
+08000c2c <write_bytes>:
+ static inline void
+write_bytes(int len, const uint8_t *buf)
+{
+#ifndef DISABLE_OLED
+ // send via SPI(1)
+ HAL_SPI_Transmit(&spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY);
+ 8000c2c: b282 uxth r2, r0
+ 8000c2e: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff
+ 8000c32: 4801 ldr r0, [pc, #4] ; (8000c38 <write_bytes+0xc>)
+ 8000c34: f000 bc1c b.w 8001470 <HAL_SPI_Transmit>
+ 8000c38: 2009e154 .word 0x2009e154
+
+08000c3c <oled_write_cmd>:
+
+// oled_write_cmd()
+//
+ void
+oled_write_cmd(uint8_t cmd)
+{
+ 8000c3c: b507 push {r0, r1, r2, lr}
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000c3e: 2201 movs r2, #1
+{
+ 8000c40: f88d 0007 strb.w r0, [sp, #7]
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000c44: 2110 movs r1, #16
+ 8000c46: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000c4a: f000 fb71 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, DC_PIN, 0);
+ 8000c4e: 2200 movs r2, #0
+ 8000c50: f44f 7180 mov.w r1, #256 ; 0x100
+ 8000c54: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000c58: f000 fb6a bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
+ 8000c5c: 2200 movs r2, #0
+ 8000c5e: 2110 movs r1, #16
+ 8000c60: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000c64: f000 fb64 bl 8001330 <HAL_GPIO_WritePin>
+
+ write_bytes(1, &cmd);
+ 8000c68: f10d 0107 add.w r1, sp, #7
+ 8000c6c: 2001 movs r0, #1
+ 8000c6e: f7ff ffdd bl 8000c2c <write_bytes>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000c72: 2201 movs r2, #1
+ 8000c74: 2110 movs r1, #16
+ 8000c76: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000c7a: f000 fb59 bl 8001330 <HAL_GPIO_WritePin>
+}
+ 8000c7e: b003 add sp, #12
+ 8000c80: f85d fb04 ldr.w pc, [sp], #4
+
+08000c84 <oled_write_cmd_sequence>:
+
+// oled_write_cmd_sequence()
+//
+ void
+oled_write_cmd_sequence(int len, const uint8_t *cmds)
+{
+ 8000c84: b570 push {r4, r5, r6, lr}
+ 8000c86: 4605 mov r5, r0
+ 8000c88: 460e mov r6, r1
+ for(int i=0; i<len; i++) {
+ 8000c8a: 2400 movs r4, #0
+ 8000c8c: 42ac cmp r4, r5
+ 8000c8e: db00 blt.n 8000c92 <oled_write_cmd_sequence+0xe>
+ oled_write_cmd(cmds[i]);
+ }
+}
+ 8000c90: bd70 pop {r4, r5, r6, pc}
+ oled_write_cmd(cmds[i]);
+ 8000c92: 5d30 ldrb r0, [r6, r4]
+ 8000c94: f7ff ffd2 bl 8000c3c <oled_write_cmd>
+ for(int i=0; i<len; i++) {
+ 8000c98: 3401 adds r4, #1
+ 8000c9a: e7f7 b.n 8000c8c <oled_write_cmd_sequence+0x8>
+
+08000c9c <oled_write_data>:
+
+// oled_write_data()
+//
+ void
+oled_write_data(int len, const uint8_t *pixels)
+{
+ 8000c9c: b538 push {r3, r4, r5, lr}
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000c9e: 2201 movs r2, #1
+{
+ 8000ca0: 4604 mov r4, r0
+ 8000ca2: 460d mov r5, r1
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000ca4: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000ca8: 2110 movs r1, #16
+ 8000caa: f000 fb41 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
+ 8000cae: 2201 movs r2, #1
+ 8000cb0: f44f 7180 mov.w r1, #256 ; 0x100
+ 8000cb4: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000cb8: f000 fb3a bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
+ 8000cbc: 2200 movs r2, #0
+ 8000cbe: 2110 movs r1, #16
+ 8000cc0: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000cc4: f000 fb34 bl 8001330 <HAL_GPIO_WritePin>
+
+ write_bytes(len, pixels);
+ 8000cc8: 4629 mov r1, r5
+ 8000cca: 4620 mov r0, r4
+ 8000ccc: f7ff ffae bl 8000c2c <write_bytes>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+}
+ 8000cd0: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr}
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000cd4: 2201 movs r2, #1
+ 8000cd6: 2110 movs r1, #16
+ 8000cd8: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000cdc: f000 bb28 b.w 8001330 <HAL_GPIO_WritePin>
+
+08000ce0 <oled_spi_setup>:
+//
+// Just setup SPI, do not reset display, etc.
+//
+ void
+oled_spi_setup(void)
+{
+ 8000ce0: b538 push {r3, r4, r5, lr}
+#ifndef DISABLE_OLED
+ // might already be setup
+ if(spi_port.Instance == SPI1) return;
+ 8000ce2: 4c0e ldr r4, [pc, #56] ; (8000d1c <oled_spi_setup+0x3c>)
+ 8000ce4: 4d0e ldr r5, [pc, #56] ; (8000d20 <oled_spi_setup+0x40>)
+ 8000ce6: 6823 ldr r3, [r4, #0]
+ 8000ce8: 42ab cmp r3, r5
+ 8000cea: d016 beq.n 8000d1a <oled_spi_setup+0x3a>
+
+ memset(&spi_port, 0, sizeof(spi_port));
+ 8000cec: f104 0008 add.w r0, r4, #8
+ 8000cf0: 225c movs r2, #92 ; 0x5c
+ 8000cf2: 2100 movs r1, #0
+ 8000cf4: f00c fcf0 bl 800d6d8 <memset>
+
+ spi_port.Instance = SPI1;
+
+ // see SPI_InitTypeDef
+ spi_port.Init.Mode = SPI_MODE_MASTER;
+ 8000cf8: f44f 7382 mov.w r3, #260 ; 0x104
+ 8000cfc: 6063 str r3, [r4, #4]
+ spi_port.Init.Direction = SPI_DIRECTION_2LINES;
+ spi_port.Init.DataSize = SPI_DATASIZE_8BIT;
+ 8000cfe: f44f 63e0 mov.w r3, #1792 ; 0x700
+ 8000d02: 60e3 str r3, [r4, #12]
+ spi_port.Init.CLKPolarity = SPI_POLARITY_LOW;
+ spi_port.Init.CLKPhase = SPI_PHASE_1EDGE;
+ spi_port.Init.NSS = SPI_NSS_SOFT;
+ spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // conservative
+ 8000d04: f44f 7000 mov.w r0, #512 ; 0x200
+ 8000d08: 2318 movs r3, #24
+ 8000d0a: e9c4 0306 strd r0, r3, [r4, #24]
+ spi_port.Instance = SPI1;
+ 8000d0e: 6025 str r5, [r4, #0]
+ spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ spi_port.Init.TIMode = SPI_TIMODE_DISABLED;
+ spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
+
+ HAL_SPI_Init(&spi_port);
+ 8000d10: 4620 mov r0, r4
+#endif
+}
+ 8000d12: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr}
+ HAL_SPI_Init(&spi_port);
+ 8000d16: f000 bb4d b.w 80013b4 <HAL_SPI_Init>
+}
+ 8000d1a: bd38 pop {r3, r4, r5, pc}
+ 8000d1c: 2009e154 .word 0x2009e154
+ 8000d20: 40013000 .word 0x40013000
+
+08000d24 <oled_setup>:
+//
+// Ok to call this lots.
+//
+ void
+oled_setup(void)
+{
+ 8000d24: b530 push {r4, r5, lr}
+ puts("oled disabled");return; // disable so I can use MCO
+#endif
+
+ static uint32_t inited;
+
+ if(inited == 0x238a572F) {
+ 8000d26: 4b31 ldr r3, [pc, #196] ; (8000dec <oled_setup+0xc8>)
+ 8000d28: 4a31 ldr r2, [pc, #196] ; (8000df0 <oled_setup+0xcc>)
+ 8000d2a: 6819 ldr r1, [r3, #0]
+ 8000d2c: 4291 cmp r1, r2
+{
+ 8000d2e: b089 sub sp, #36 ; 0x24
+ if(inited == 0x238a572F) {
+ 8000d30: d058 beq.n 8000de4 <oled_setup+0xc0>
+ return;
+ }
+ inited = 0x238a572F;
+ 8000d32: 601a str r2, [r3, #0]
+
+ // enable some internal clocks
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ 8000d34: 4b2f ldr r3, [pc, #188] ; (8000df4 <oled_setup+0xd0>)
+ __HAL_RCC_SPI1_CLK_ENABLE();
+
+ // simple pins
+ GPIO_InitTypeDef setup = {
+ 8000d36: 4d30 ldr r5, [pc, #192] ; (8000df8 <oled_setup+0xd4>)
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ 8000d38: 6cda ldr r2, [r3, #76] ; 0x4c
+ 8000d3a: f042 0201 orr.w r2, r2, #1
+ 8000d3e: 64da str r2, [r3, #76] ; 0x4c
+ 8000d40: 6cda ldr r2, [r3, #76] ; 0x4c
+ 8000d42: f002 0201 and.w r2, r2, #1
+ 8000d46: 9201 str r2, [sp, #4]
+ 8000d48: 9a01 ldr r2, [sp, #4]
+ __HAL_RCC_SPI1_CLK_ENABLE();
+ 8000d4a: 6e1a ldr r2, [r3, #96] ; 0x60
+ 8000d4c: f442 5280 orr.w r2, r2, #4096 ; 0x1000
+ 8000d50: 661a str r2, [r3, #96] ; 0x60
+ 8000d52: 6e1b ldr r3, [r3, #96] ; 0x60
+ 8000d54: f403 5380 and.w r3, r3, #4096 ; 0x1000
+ 8000d58: 9302 str r3, [sp, #8]
+ 8000d5a: 9b02 ldr r3, [sp, #8]
+ GPIO_InitTypeDef setup = {
+ 8000d5c: cd0f ldmia r5!, {r0, r1, r2, r3}
+ 8000d5e: ac03 add r4, sp, #12
+ 8000d60: c40f stmia r4!, {r0, r1, r2, r3}
+ 8000d62: 682b ldr r3, [r5, #0]
+ 8000d64: 6023 str r3, [r4, #0]
+ .Mode = GPIO_MODE_OUTPUT_PP,
+ .Pull = GPIO_NOPULL,
+ .Speed = GPIO_SPEED_FREQ_MEDIUM,
+ .Alternate = 0,
+ };
+ HAL_GPIO_Init(GPIOA, &setup);
+ 8000d66: a903 add r1, sp, #12
+ 8000d68: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000d6c: f000 f966 bl 800103c <HAL_GPIO_Init>
+
+ // starting values
+ HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1);
+ 8000d70: 2201 movs r2, #1
+ 8000d72: f44f 71a8 mov.w r1, #336 ; 0x150
+ 8000d76: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000d7a: f000 fad9 bl 8001330 <HAL_GPIO_WritePin>
+
+ // SPI pins
+ setup.Pin = SPI_SCK | SPI_MOSI;
+ setup.Mode = GPIO_MODE_AF_PP;
+ 8000d7e: 2402 movs r4, #2
+ 8000d80: 23a0 movs r3, #160 ; 0xa0
+ 8000d82: e9cd 3403 strd r3, r4, [sp, #12]
+ setup.Alternate = GPIO_AF5_SPI1;
+ HAL_GPIO_Init(GPIOA, &setup);
+ 8000d86: a903 add r1, sp, #12
+ setup.Alternate = GPIO_AF5_SPI1;
+ 8000d88: 2305 movs r3, #5
+ HAL_GPIO_Init(GPIOA, &setup);
+ 8000d8a: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ setup.Alternate = GPIO_AF5_SPI1;
+ 8000d8e: 9307 str r3, [sp, #28]
+ HAL_GPIO_Init(GPIOA, &setup);
+ 8000d90: f000 f954 bl 800103c <HAL_GPIO_Init>
+
+ // lock the RESET pin so that St's DFU code doesn't clear screen
+ // it might be trying to use it as a MISO signal for SPI loading
+ HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN);
+ 8000d94: f44f 71a8 mov.w r1, #336 ; 0x150
+ 8000d98: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000d9c: f000 fad1 bl 8001342 <HAL_GPIO_LockPin>
+
+ // 10ms low-going pulse on reset pin
+ delay_ms(1);
+ 8000da0: 2001 movs r0, #1
+ 8000da2: f002 fdbf bl 8003924 <delay_ms>
+ HAL_GPIO_WritePin(GPIOA, RESET_PIN, 0);
+ 8000da6: 2200 movs r2, #0
+ 8000da8: 2140 movs r1, #64 ; 0x40
+ 8000daa: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000dae: f000 fabf bl 8001330 <HAL_GPIO_WritePin>
+ delay_ms(10);
+ 8000db2: 200a movs r0, #10
+ 8000db4: f002 fdb6 bl 8003924 <delay_ms>
+ HAL_GPIO_WritePin(GPIOA, RESET_PIN, 1);
+ 8000db8: 2201 movs r2, #1
+ 8000dba: 2140 movs r1, #64 ; 0x40
+ 8000dbc: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000dc0: f000 fab6 bl 8001330 <HAL_GPIO_WritePin>
+
+ oled_spi_setup();
+ 8000dc4: f7ff ff8c bl 8000ce0 <oled_spi_setup>
+ // this code:
+ // '0x37c', '0x1700', '0x603'
+ //SPI1->CR1 = 0x354;
+
+ // write a sequence to reset things
+ if(is_mk5()) {
+ 8000dc8: f002 fe48 bl 8003a5c <is_mk5>
+ 8000dcc: b160 cbz r0, 8000de8 <oled_setup+0xc4>
+ // note: +12v is always on now, this line supports older revs
+ HAL_GPIO_WritePin(GPIOC, VCC_EN_PIN, 1);
+ 8000dce: 4621 mov r1, r4
+ 8000dd0: 480a ldr r0, [pc, #40] ; (8000dfc <oled_setup+0xd8>)
+ 8000dd2: 2201 movs r2, #1
+ 8000dd4: f000 faac bl 8001330 <HAL_GPIO_WritePin>
+
+ oled_write_cmd_sequence(sizeof(reset_commands_mk5), reset_commands_mk5);
+ 8000dd8: 4909 ldr r1, [pc, #36] ; (8000e00 <oled_setup+0xdc>)
+ } else {
+ oled_write_cmd_sequence(sizeof(reset_commands_mk4), reset_commands_mk4);
+ 8000dda: 2019 movs r0, #25
+ 8000ddc: f7ff ff52 bl 8000c84 <oled_write_cmd_sequence>
+ }
+
+ rng_delay();
+ 8000de0: f001 fce2 bl 80027a8 <rng_delay>
+}
+ 8000de4: b009 add sp, #36 ; 0x24
+ 8000de6: bd30 pop {r4, r5, pc}
+ oled_write_cmd_sequence(sizeof(reset_commands_mk4), reset_commands_mk4);
+ 8000de8: 4906 ldr r1, [pc, #24] ; (8000e04 <oled_setup+0xe0>)
+ 8000dea: e7f6 b.n 8000dda <oled_setup+0xb6>
+ 8000dec: 2009e150 .word 0x2009e150
+ 8000df0: 238a572f .word 0x238a572f
+ 8000df4: 40021000 .word 0x40021000
+ 8000df8: 0800d7fc .word 0x0800d7fc
+ 8000dfc: 48000800 .word 0x48000800
+ 8000e00: 0800d845 .word 0x0800d845
+ 8000e04: 0800d82c .word 0x0800d82c
+
+08000e08 <oled_show_raw>:
+//
+// No decompression.
+//
+ void
+oled_show_raw(uint32_t len, const uint8_t *pixels)
+{
+ 8000e08: b538 push {r3, r4, r5, lr}
+ 8000e0a: 4604 mov r4, r0
+ 8000e0c: 460d mov r5, r1
+ oled_setup();
+ 8000e0e: f7ff ff89 bl 8000d24 <oled_setup>
+
+ oled_write_cmd_sequence(sizeof(before_show), before_show);
+ 8000e12: 4912 ldr r1, [pc, #72] ; (8000e5c <oled_show_raw+0x54>)
+ 8000e14: 2006 movs r0, #6
+ 8000e16: f7ff ff35 bl 8000c84 <oled_write_cmd_sequence>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000e1a: 2201 movs r2, #1
+ 8000e1c: 2110 movs r1, #16
+ 8000e1e: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e22: f000 fa85 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
+ 8000e26: 2201 movs r2, #1
+ 8000e28: f44f 7180 mov.w r1, #256 ; 0x100
+ 8000e2c: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e30: f000 fa7e bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
+ 8000e34: 2200 movs r2, #0
+ 8000e36: 2110 movs r1, #16
+ 8000e38: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e3c: f000 fa78 bl 8001330 <HAL_GPIO_WritePin>
+
+ write_bytes(len, pixels);
+ 8000e40: 4629 mov r1, r5
+ 8000e42: 4620 mov r0, r4
+ 8000e44: f7ff fef2 bl 8000c2c <write_bytes>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000e48: 2201 movs r2, #1
+ 8000e4a: 2110 movs r1, #16
+ 8000e4c: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e50: f000 fa6e bl 8001330 <HAL_GPIO_WritePin>
+ rng_delay();
+}
+ 8000e54: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr}
+ rng_delay();
+ 8000e58: f001 bca6 b.w 80027a8 <rng_delay>
+ 8000e5c: 0800d826 .word 0x0800d826
+
+08000e60 <oled_show>:
+//
+// Perform simple RLE decompression.
+//
+ void
+oled_show(const uint8_t *pixels)
+{
+ 8000e60: b530 push {r4, r5, lr}
+ 8000e62: b0a1 sub sp, #132 ; 0x84
+ 8000e64: 4604 mov r4, r0
+ oled_setup();
+ 8000e66: f7ff ff5d bl 8000d24 <oled_setup>
+
+ oled_write_cmd_sequence(sizeof(before_show), before_show);
+ 8000e6a: 491d ldr r1, [pc, #116] ; (8000ee0 <oled_show+0x80>)
+ 8000e6c: 2006 movs r0, #6
+ 8000e6e: f7ff ff09 bl 8000c84 <oled_write_cmd_sequence>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000e72: 2201 movs r2, #1
+ 8000e74: 2110 movs r1, #16
+ 8000e76: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e7a: f000 fa59 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
+ 8000e7e: 2201 movs r2, #1
+ 8000e80: f44f 7180 mov.w r1, #256 ; 0x100
+ 8000e84: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e88: f000 fa52 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
+ 8000e8c: 2200 movs r2, #0
+ 8000e8e: 2110 movs r1, #16
+ 8000e90: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000e94: f000 fa4c bl 8001330 <HAL_GPIO_WritePin>
+ uint8_t buf[127];
+ const uint8_t *p = pixels;
+
+ // NOTE: must also update code in oled_show_progress, which dups this heavily.
+ while(1) {
+ uint8_t hdr = *(p++);
+ 8000e98: 7823 ldrb r3, [r4, #0]
+ if(!hdr) break;
+ 8000e9a: b1b3 cbz r3, 8000eca <oled_show+0x6a>
+
+ uint8_t len = hdr & 0x7f;
+ 8000e9c: f003 057f and.w r5, r3, #127 ; 0x7f
+ if(hdr & 0x80) {
+ 8000ea0: 061b lsls r3, r3, #24
+ 8000ea2: d50b bpl.n 8000ebc <oled_show+0x5c>
+ uint8_t hdr = *(p++);
+ 8000ea4: 3401 adds r4, #1
+ // random bytes follow
+ memcpy(buf, p, len);
+ 8000ea6: 4621 mov r1, r4
+ 8000ea8: 462a mov r2, r5
+ 8000eaa: 4668 mov r0, sp
+ 8000eac: f00c fbec bl 800d688 <memcpy>
+ p += len;
+ 8000eb0: 442c add r4, r5
+ // repeat same byte
+ memset(buf, *p, len);
+ p++;
+ }
+
+ write_bytes(len, buf);
+ 8000eb2: 4669 mov r1, sp
+ 8000eb4: 4628 mov r0, r5
+ 8000eb6: f7ff feb9 bl 8000c2c <write_bytes>
+ while(1) {
+ 8000eba: e7ed b.n 8000e98 <oled_show+0x38>
+ memset(buf, *p, len);
+ 8000ebc: 7861 ldrb r1, [r4, #1]
+ 8000ebe: 462a mov r2, r5
+ 8000ec0: 4668 mov r0, sp
+ 8000ec2: f00c fc09 bl 800d6d8 <memset>
+ p++;
+ 8000ec6: 3402 adds r4, #2
+ 8000ec8: e7f3 b.n 8000eb2 <oled_show+0x52>
+ }
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000eca: 2201 movs r2, #1
+ 8000ecc: 2110 movs r1, #16
+ 8000ece: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000ed2: f000 fa2d bl 8001330 <HAL_GPIO_WritePin>
+ rng_delay();
+ 8000ed6: f001 fc67 bl 80027a8 <rng_delay>
+}
+ 8000eda: b021 add sp, #132 ; 0x84
+ 8000edc: bd30 pop {r4, r5, pc}
+ 8000ede: bf00 nop
+ 8000ee0: 0800d826 .word 0x0800d826
+
+08000ee4 <oled_show_progress>:
+//
+// Perform simple RLE decompression, and add a bar on final screen line.
+//
+ void
+oled_show_progress(const uint8_t *pixels, int progress)
+{
+ 8000ee4: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr}
+ 8000ee8: b0a1 sub sp, #132 ; 0x84
+ 8000eea: 460d mov r5, r1
+ 8000eec: 4606 mov r6, r0
+ oled_setup();
+ 8000eee: f7ff ff19 bl 8000d24 <oled_setup>
+
+ oled_write_cmd_sequence(sizeof(before_show), before_show);
+ 8000ef2: 493b ldr r1, [pc, #236] ; (8000fe0 <oled_show_progress+0xfc>)
+ 8000ef4: 2006 movs r0, #6
+ 8000ef6: f7ff fec5 bl 8000c84 <oled_write_cmd_sequence>
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000efa: 2201 movs r2, #1
+ 8000efc: 2110 movs r1, #16
+ 8000efe: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000f02: f000 fa15 bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
+ 8000f06: 2201 movs r2, #1
+ 8000f08: f44f 7180 mov.w r1, #256 ; 0x100
+ 8000f0c: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000f10: f000 fa0e bl 8001330 <HAL_GPIO_WritePin>
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
+ 8000f14: 2110 movs r1, #16
+ 8000f16: 2200 movs r2, #0
+ 8000f18: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000f1c: f000 fa08 bl 8001330 <HAL_GPIO_WritePin>
+
+ uint8_t buf[127];
+ const uint8_t *p = pixels;
+
+ const uint16_t p_start = 896;
+ uint32_t p_count = 1280 * progress / 1000;
+ 8000f20: f44f 61a0 mov.w r1, #1280 ; 0x500
+ 8000f24: 434d muls r5, r1
+ 8000f26: 2400 movs r4, #0
+ 8000f28: f44f 717a mov.w r1, #1000 ; 0x3e8
+ 8000f2c: fb95 f5f1 sdiv r5, r5, r1
+
+ if(p_count > 128) p_count = 128;
+ 8000f30: 2d80 cmp r5, #128 ; 0x80
+ 8000f32: bf28 it cs
+ 8000f34: 2580 movcs r5, #128 ; 0x80
+ uint32_t p_count = 1280 * progress / 1000;
+ 8000f36: 46a0 mov r8, r4
+
+ bool last_line = false;
+
+ uint16_t offset = 0;
+ while(1) {
+ uint8_t hdr = *(p++);
+ 8000f38: 7833 ldrb r3, [r6, #0]
+ if(hdr == 0) break;
+ 8000f3a: 2b00 cmp r3, #0
+ 8000f3c: d045 beq.n 8000fca <oled_show_progress+0xe6>
+
+ uint8_t len = hdr & 0x7f;
+ 8000f3e: f003 097f and.w r9, r3, #127 ; 0x7f
+ if(hdr & 0x80) {
+ 8000f42: 061b lsls r3, r3, #24
+ 8000f44: d524 bpl.n 8000f90 <oled_show_progress+0xac>
+ uint8_t hdr = *(p++);
+ 8000f46: 3601 adds r6, #1
+ // random bytes follow
+ memcpy(buf, p, len);
+ 8000f48: 4631 mov r1, r6
+ 8000f4a: 464a mov r2, r9
+ 8000f4c: 4668 mov r0, sp
+ 8000f4e: f00c fb9b bl 800d688 <memcpy>
+ p += len;
+ 8000f52: 444e add r6, r9
+ // repeat same byte
+ memset(buf, *p, len);
+ p++;
+ }
+
+ if(!last_line && (offset+len) >= p_start) {
+ 8000f54: f1b8 0f00 cmp.w r8, #0
+ 8000f58: d117 bne.n 8000f8a <oled_show_progress+0xa6>
+ 8000f5a: eb04 0309 add.w r3, r4, r9
+ 8000f5e: f5b3 7f60 cmp.w r3, #896 ; 0x380
+ 8000f62: db29 blt.n 8000fb8 <oled_show_progress+0xd4>
+ last_line = true;
+
+ // adjust so we're aligned w/ last line
+ int h = p_start - offset;
+ if(h) {
+ 8000f64: f5d4 7460 rsbs r4, r4, #896 ; 0x380
+ 8000f68: d00d beq.n 8000f86 <oled_show_progress+0xa2>
+ write_bytes(h, buf);
+ 8000f6a: 4669 mov r1, sp
+ 8000f6c: 4620 mov r0, r4
+ memmove(buf, buf+h, len-h);
+ 8000f6e: eba9 0904 sub.w r9, r9, r4
+ write_bytes(h, buf);
+ 8000f72: f7ff fe5b bl 8000c2c <write_bytes>
+ memmove(buf, buf+h, len-h);
+ 8000f76: 464a mov r2, r9
+ 8000f78: eb0d 0104 add.w r1, sp, r4
+ 8000f7c: 4668 mov r0, sp
+ 8000f7e: f00c fb91 bl 800d6a4 <memmove>
+ len -= h;
+ 8000f82: fa5f f989 uxtb.w r9, r9
+ offset += h;
+ 8000f86: f44f 7460 mov.w r4, #896 ; 0x380
+ }
+ }
+
+ if(last_line) {
+ 8000f8a: 466b mov r3, sp
+ while(1) {
+ 8000f8c: 462f mov r7, r5
+ 8000f8e: e00c b.n 8000faa <oled_show_progress+0xc6>
+ memset(buf, *p, len);
+ 8000f90: 7871 ldrb r1, [r6, #1]
+ 8000f92: 464a mov r2, r9
+ 8000f94: 4668 mov r0, sp
+ 8000f96: f00c fb9f bl 800d6d8 <memset>
+ p++;
+ 8000f9a: 3602 adds r6, #2
+ 8000f9c: e7da b.n 8000f54 <oled_show_progress+0x70>
+ for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
+ buf[j] |= 0x80;
+ 8000f9e: 7819 ldrb r1, [r3, #0]
+ 8000fa0: f061 017f orn r1, r1, #127 ; 0x7f
+ 8000fa4: f803 1b01 strb.w r1, [r3], #1
+ for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
+ 8000fa8: 3f01 subs r7, #1
+ 8000faa: b117 cbz r7, 8000fb2 <oled_show_progress+0xce>
+ 8000fac: 1bea subs r2, r5, r7
+ 8000fae: 454a cmp r2, r9
+ 8000fb0: dbf5 blt.n 8000f9e <oled_show_progress+0xba>
+ 8000fb2: f04f 0801 mov.w r8, #1
+ 8000fb6: e000 b.n 8000fba <oled_show_progress+0xd6>
+ 8000fb8: 462f mov r7, r5
+ }
+ }
+
+ write_bytes(len, buf);
+ 8000fba: 4669 mov r1, sp
+ 8000fbc: 4648 mov r0, r9
+ offset += len;
+ 8000fbe: 444c add r4, r9
+ write_bytes(len, buf);
+ 8000fc0: f7ff fe34 bl 8000c2c <write_bytes>
+ offset += len;
+ 8000fc4: b2a4 uxth r4, r4
+ while(1) {
+ 8000fc6: 463d mov r5, r7
+ 8000fc8: e7b6 b.n 8000f38 <oled_show_progress+0x54>
+ }
+
+ HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
+ 8000fca: 2201 movs r2, #1
+ 8000fcc: 2110 movs r1, #16
+ 8000fce: f04f 4090 mov.w r0, #1207959552 ; 0x48000000
+ 8000fd2: f000 f9ad bl 8001330 <HAL_GPIO_WritePin>
+ rng_delay();
+ 8000fd6: f001 fbe7 bl 80027a8 <rng_delay>
+}
+ 8000fda: b021 add sp, #132 ; 0x84
+ 8000fdc: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc}
+ 8000fe0: 0800d826 .word 0x0800d826
+
+08000fe4 <oled_factory_busy>:
+
+// oled_factory_busy()
+//
+ void
+oled_factory_busy(void)
+{
+ 8000fe4: b510 push {r4, lr}
+ 8000fe6: b0a0 sub sp, #128 ; 0x80
+ 8000fe8: 466a mov r2, sp
+ 8000fea: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff
+ 8000fee: 4614 mov r4, r2
+
+ uint8_t data[128];
+
+ for(int x=0; x<128; x++) {
+ // each byte here is a vertical column, 8 pixels tall, MSB at bottom
+ data[x] = (1<<(7 - (x%8)));
+ 8000ff0: 2001 movs r0, #1
+ 8000ff2: f003 0107 and.w r1, r3, #7
+ for(int x=0; x<128; x++) {
+ 8000ff6: 3b01 subs r3, #1
+ data[x] = (1<<(7 - (x%8)));
+ 8000ff8: fa00 f101 lsl.w r1, r0, r1
+ for(int x=0; x<128; x++) {
+ 8000ffc: f113 0f81 cmn.w r3, #129 ; 0x81
+ data[x] = (1<<(7 - (x%8)));
+ 8001000: f802 1b01 strb.w r1, [r2], #1
+ for(int x=0; x<128; x++) {
+ 8001004: d1f5 bne.n 8000ff2 <oled_factory_busy+0xe>
+ }
+
+ oled_write_cmd_sequence(sizeof(setup), setup);
+ 8001006: 490a ldr r1, [pc, #40] ; (8001030 <oled_factory_busy+0x4c>)
+ 8001008: 2006 movs r0, #6
+ 800100a: f7ff fe3b bl 8000c84 <oled_write_cmd_sequence>
+ oled_write_data(sizeof(data), data);
+ 800100e: 4621 mov r1, r4
+ 8001010: 2080 movs r0, #128 ; 0x80
+ 8001012: f7ff fe43 bl 8000c9c <oled_write_data>
+ if(is_mk5()) {
+ 8001016: f002 fd21 bl 8003a5c <is_mk5>
+ 800101a: b128 cbz r0, 8001028 <oled_factory_busy+0x44>
+ oled_write_cmd_sequence(sizeof(animate_mk5), animate_mk5);
+ 800101c: 4905 ldr r1, [pc, #20] ; (8001034 <oled_factory_busy+0x50>)
+ 800101e: 200d movs r0, #13
+ } else {
+ oled_write_cmd_sequence(sizeof(animate_mk4), animate_mk4);
+ 8001020: f7ff fe30 bl 8000c84 <oled_write_cmd_sequence>
+ }
+}
+ 8001024: b020 add sp, #128 ; 0x80
+ 8001026: bd10 pop {r4, pc}
+ oled_write_cmd_sequence(sizeof(animate_mk4), animate_mk4);
+ 8001028: 4903 ldr r1, [pc, #12] ; (8001038 <oled_factory_busy+0x54>)
+ 800102a: 2009 movs r0, #9
+ 800102c: e7f8 b.n 8001020 <oled_factory_busy+0x3c>
+ 800102e: bf00 nop
+ 8001030: 0800d85e .word 0x0800d85e
+ 8001034: 0800d819 .word 0x0800d819
+ 8001038: 0800d810 .word 0x0800d810
+
+0800103c <HAL_GPIO_Init>:
+ * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
+ * the configuration information for the specified GPIO peripheral.
+ * @retval None
+ */
+void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
+{
+ 800103c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
+ {
+ /* Enable SYSCFG Clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 8001040: f8df 81b4 ldr.w r8, [pc, #436] ; 80011f8 <HAL_GPIO_Init+0x1bc>
+ temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ SYSCFG->EXTICR[position >> 2] = temp;
+
+ /* Clear EXTI line configuration */
+ temp = EXTI->IMR1;
+ 8001044: 4c6a ldr r4, [pc, #424] ; (80011f0 <HAL_GPIO_Init+0x1b4>)
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ 8001046: f8df 91b4 ldr.w r9, [pc, #436] ; 80011fc <HAL_GPIO_Init+0x1c0>
+{
+ 800104a: b085 sub sp, #20
+ uint32_t position = 0x00;
+ 800104c: 2300 movs r3, #0
+ while (((GPIO_Init->Pin) >> position) != RESET)
+ 800104e: 680a ldr r2, [r1, #0]
+ 8001050: fa32 f503 lsrs.w r5, r2, r3
+ 8001054: d102 bne.n 800105c <HAL_GPIO_Init+0x20>
+ }
+ }
+
+ position++;
+ }
+}
+ 8001056: b005 add sp, #20
+ 8001058: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
+ iocurrent = (GPIO_Init->Pin) & (1U << position);
+ 800105c: 2701 movs r7, #1
+ 800105e: 409f lsls r7, r3
+ if(iocurrent)
+ 8001060: 403a ands r2, r7
+ 8001062: f000 80b4 beq.w 80011ce <HAL_GPIO_Init+0x192>
+ if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
+ 8001066: 684d ldr r5, [r1, #4]
+ 8001068: f025 0a10 bic.w sl, r5, #16
+ 800106c: f1ba 0f02 cmp.w sl, #2
+ 8001070: d116 bne.n 80010a0 <HAL_GPIO_Init+0x64>
+ temp = GPIOx->AFR[position >> 3];
+ 8001072: ea4f 0ed3 mov.w lr, r3, lsr #3
+ 8001076: eb00 0e8e add.w lr, r0, lr, lsl #2
+ temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+ 800107a: f003 0b07 and.w fp, r3, #7
+ temp = GPIOx->AFR[position >> 3];
+ 800107e: f8de 6020 ldr.w r6, [lr, #32]
+ temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+ 8001082: ea4f 0b8b mov.w fp, fp, lsl #2
+ 8001086: f04f 0c0f mov.w ip, #15
+ 800108a: fa0c fc0b lsl.w ip, ip, fp
+ 800108e: ea26 0c0c bic.w ip, r6, ip
+ temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
+ 8001092: 690e ldr r6, [r1, #16]
+ 8001094: fa06 f60b lsl.w r6, r6, fp
+ 8001098: ea46 060c orr.w r6, r6, ip
+ GPIOx->AFR[position >> 3] = temp;
+ 800109c: f8ce 6020 str.w r6, [lr, #32]
+ temp = GPIOx->MODER;
+ 80010a0: f8d0 b000 ldr.w fp, [r0]
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2));
+ 80010a4: ea4f 0e43 mov.w lr, r3, lsl #1
+ 80010a8: f04f 0c03 mov.w ip, #3
+ 80010ac: fa0c fc0e lsl.w ip, ip, lr
+ 80010b0: ea6f 060c mvn.w r6, ip
+ 80010b4: ea2b 0b0c bic.w fp, fp, ip
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
+ 80010b8: f005 0c03 and.w ip, r5, #3
+ 80010bc: fa0c fc0e lsl.w ip, ip, lr
+ if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ 80010c0: f10a 3aff add.w sl, sl, #4294967295 ; 0xffffffff
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
+ 80010c4: ea4c 0c0b orr.w ip, ip, fp
+ if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ 80010c8: f1ba 0f01 cmp.w sl, #1
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2));
+ 80010cc: 9601 str r6, [sp, #4]
+ GPIOx->MODER = temp;
+ 80010ce: f8c0 c000 str.w ip, [r0]
+ if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ 80010d2: d815 bhi.n 8001100 <HAL_GPIO_Init+0xc4>
+ temp = GPIOx->OSPEEDR;
+ 80010d4: f8d0 c008 ldr.w ip, [r0, #8]
+ temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
+ 80010d8: ea06 0c0c and.w ip, r6, ip
+ temp |= (GPIO_Init->Speed << (position * 2));
+ 80010dc: 68ce ldr r6, [r1, #12]
+ 80010de: fa06 fa0e lsl.w sl, r6, lr
+ 80010e2: ea4a 0c0c orr.w ip, sl, ip
+ GPIOx->OSPEEDR = temp;
+ 80010e6: f8c0 c008 str.w ip, [r0, #8]
+ temp = GPIOx->OTYPER;
+ 80010ea: f8d0 c004 ldr.w ip, [r0, #4]
+ temp &= ~(GPIO_OTYPER_OT0 << position) ;
+ 80010ee: ea2c 0707 bic.w r7, ip, r7
+ temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
+ 80010f2: f3c5 1c00 ubfx ip, r5, #4, #1
+ 80010f6: fa0c fc03 lsl.w ip, ip, r3
+ 80010fa: ea4c 0707 orr.w r7, ip, r7
+ GPIOx->OTYPER = temp;
+ 80010fe: 6047 str r7, [r0, #4]
+ temp = GPIOx->PUPDR;
+ 8001100: 68c7 ldr r7, [r0, #12]
+ temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
+ 8001102: 9e01 ldr r6, [sp, #4]
+ 8001104: 4037 ands r7, r6
+ temp |= ((GPIO_Init->Pull) << (position * 2));
+ 8001106: 688e ldr r6, [r1, #8]
+ 8001108: fa06 f60e lsl.w r6, r6, lr
+ 800110c: 433e orrs r6, r7
+ GPIOx->PUPDR = temp;
+ 800110e: 60c6 str r6, [r0, #12]
+ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
+ 8001110: 00ee lsls r6, r5, #3
+ 8001112: d55c bpl.n 80011ce <HAL_GPIO_Init+0x192>
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 8001114: f8d8 6060 ldr.w r6, [r8, #96] ; 0x60
+ 8001118: f046 0601 orr.w r6, r6, #1
+ 800111c: f8c8 6060 str.w r6, [r8, #96] ; 0x60
+ 8001120: f8d8 6060 ldr.w r6, [r8, #96] ; 0x60
+ 8001124: f023 0703 bic.w r7, r3, #3
+ 8001128: f107 4780 add.w r7, r7, #1073741824 ; 0x40000000
+ 800112c: f006 0601 and.w r6, r6, #1
+ 8001130: f507 3780 add.w r7, r7, #65536 ; 0x10000
+ 8001134: 9603 str r6, [sp, #12]
+ temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 8001136: f003 0c03 and.w ip, r3, #3
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ 800113a: 9e03 ldr r6, [sp, #12]
+ temp = SYSCFG->EXTICR[position >> 2];
+ 800113c: f8d7 a008 ldr.w sl, [r7, #8]
+ temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 8001140: f04f 0e0f mov.w lr, #15
+ 8001144: ea4f 0c8c mov.w ip, ip, lsl #2
+ 8001148: fa0e f60c lsl.w r6, lr, ip
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ 800114c: f1b0 4f90 cmp.w r0, #1207959552 ; 0x48000000
+ temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 8001150: ea2a 0e06 bic.w lr, sl, r6
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ 8001154: d03d beq.n 80011d2 <HAL_GPIO_Init+0x196>
+ 8001156: 4e27 ldr r6, [pc, #156] ; (80011f4 <HAL_GPIO_Init+0x1b8>)
+ 8001158: 42b0 cmp r0, r6
+ 800115a: d03c beq.n 80011d6 <HAL_GPIO_Init+0x19a>
+ 800115c: f506 6680 add.w r6, r6, #1024 ; 0x400
+ 8001160: 42b0 cmp r0, r6
+ 8001162: d03a beq.n 80011da <HAL_GPIO_Init+0x19e>
+ 8001164: f506 6680 add.w r6, r6, #1024 ; 0x400
+ 8001168: 42b0 cmp r0, r6
+ 800116a: d038 beq.n 80011de <HAL_GPIO_Init+0x1a2>
+ 800116c: f506 6680 add.w r6, r6, #1024 ; 0x400
+ 8001170: 42b0 cmp r0, r6
+ 8001172: d036 beq.n 80011e2 <HAL_GPIO_Init+0x1a6>
+ 8001174: f506 6680 add.w r6, r6, #1024 ; 0x400
+ 8001178: 42b0 cmp r0, r6
+ 800117a: d034 beq.n 80011e6 <HAL_GPIO_Init+0x1aa>
+ 800117c: 4548 cmp r0, r9
+ 800117e: d034 beq.n 80011ea <HAL_GPIO_Init+0x1ae>
+ 8001180: f506 6600 add.w r6, r6, #2048 ; 0x800
+ 8001184: 42b0 cmp r0, r6
+ 8001186: bf0c ite eq
+ 8001188: 2607 moveq r6, #7
+ 800118a: 2608 movne r6, #8
+ 800118c: fa06 f60c lsl.w r6, r6, ip
+ 8001190: ea46 060e orr.w r6, r6, lr
+ SYSCFG->EXTICR[position >> 2] = temp;
+ 8001194: 60be str r6, [r7, #8]
+ temp = EXTI->IMR1;
+ 8001196: 6826 ldr r6, [r4, #0]
+ temp &= ~((uint32_t)iocurrent);
+ 8001198: 43d7 mvns r7, r2
+ if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
+ 800119a: f415 3f80 tst.w r5, #65536 ; 0x10000
+ temp &= ~((uint32_t)iocurrent);
+ 800119e: bf0c ite eq
+ 80011a0: 403e andeq r6, r7
+ temp |= iocurrent;
+ 80011a2: 4316 orrne r6, r2
+ EXTI->IMR1 = temp;
+ 80011a4: 6026 str r6, [r4, #0]
+ temp = EXTI->EMR1;
+ 80011a6: 6866 ldr r6, [r4, #4]
+ if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
+ 80011a8: f415 3f00 tst.w r5, #131072 ; 0x20000
+ temp &= ~((uint32_t)iocurrent);
+ 80011ac: bf0c ite eq
+ 80011ae: 403e andeq r6, r7
+ temp |= iocurrent;
+ 80011b0: 4316 orrne r6, r2
+ EXTI->EMR1 = temp;
+ 80011b2: 6066 str r6, [r4, #4]
+ temp = EXTI->RTSR1;
+ 80011b4: 68a6 ldr r6, [r4, #8]
+ if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
+ 80011b6: f415 1f80 tst.w r5, #1048576 ; 0x100000
+ temp &= ~((uint32_t)iocurrent);
+ 80011ba: bf0c ite eq
+ 80011bc: 403e andeq r6, r7
+ temp |= iocurrent;
+ 80011be: 4316 orrne r6, r2
+ EXTI->RTSR1 = temp;
+ 80011c0: 60a6 str r6, [r4, #8]
+ temp = EXTI->FTSR1;
+ 80011c2: 68e6 ldr r6, [r4, #12]
+ if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
+ 80011c4: 02ad lsls r5, r5, #10
+ temp &= ~((uint32_t)iocurrent);
+ 80011c6: bf54 ite pl
+ 80011c8: 403e andpl r6, r7
+ temp |= iocurrent;
+ 80011ca: 4316 orrmi r6, r2
+ EXTI->FTSR1 = temp;
+ 80011cc: 60e6 str r6, [r4, #12]
+ position++;
+ 80011ce: 3301 adds r3, #1
+ 80011d0: e73d b.n 800104e <HAL_GPIO_Init+0x12>
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ 80011d2: 2600 movs r6, #0
+ 80011d4: e7da b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011d6: 2601 movs r6, #1
+ 80011d8: e7d8 b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011da: 2602 movs r6, #2
+ 80011dc: e7d6 b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011de: 2603 movs r6, #3
+ 80011e0: e7d4 b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011e2: 2604 movs r6, #4
+ 80011e4: e7d2 b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011e6: 2605 movs r6, #5
+ 80011e8: e7d0 b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011ea: 2606 movs r6, #6
+ 80011ec: e7ce b.n 800118c <HAL_GPIO_Init+0x150>
+ 80011ee: bf00 nop
+ 80011f0: 40010400 .word 0x40010400
+ 80011f4: 48000400 .word 0x48000400
+ 80011f8: 40021000 .word 0x40021000
+ 80011fc: 48001800 .word 0x48001800
+
+08001200 <HAL_GPIO_DeInit>:
+ * @param GPIO_Pin: specifies the port bit to be written.
+ * This parameter can be one of GPIO_PIN_x where x can be (0..15).
+ * @retval None
+ */
+void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
+{
+ 8001200: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
+ {
+ tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
+ SYSCFG->EXTICR[position >> 2] &= ~tmp;
+
+ /* Clear EXTI line configuration */
+ EXTI->IMR1 &= ~((uint32_t)iocurrent);
+ 8001204: 4c43 ldr r4, [pc, #268] ; (8001314 <HAL_GPIO_DeInit+0x114>)
+ if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
+ 8001206: f8df a114 ldr.w sl, [pc, #276] ; 800131c <HAL_GPIO_DeInit+0x11c>
+ 800120a: f8df b114 ldr.w fp, [pc, #276] ; 8001320 <HAL_GPIO_DeInit+0x120>
+ uint32_t position = 0x00;
+ 800120e: 2200 movs r2, #0
+ iocurrent = (GPIO_Pin) & (1U << position);
+ 8001210: f04f 0901 mov.w r9, #1
+ while ((GPIO_Pin >> position) != RESET)
+ 8001214: fa31 f302 lsrs.w r3, r1, r2
+ 8001218: d101 bne.n 800121e <HAL_GPIO_DeInit+0x1e>
+ }
+ }
+
+ position++;
+ }
+}
+ 800121a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
+ iocurrent = (GPIO_Pin) & (1U << position);
+ 800121e: fa09 f802 lsl.w r8, r9, r2
+ if (iocurrent)
+ 8001222: ea18 0c01 ands.w ip, r8, r1
+ 8001226: d064 beq.n 80012f2 <HAL_GPIO_DeInit+0xf2>
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2));
+ 8001228: 6805 ldr r5, [r0, #0]
+ 800122a: 2303 movs r3, #3
+ 800122c: 0056 lsls r6, r2, #1
+ 800122e: fa03 f606 lsl.w r6, r3, r6
+ GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+ 8001232: fa22 fe03 lsr.w lr, r2, r3
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2));
+ 8001236: 4335 orrs r5, r6
+ 8001238: eb00 0e8e add.w lr, r0, lr, lsl #2
+ 800123c: 6005 str r5, [r0, #0]
+ GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+ 800123e: f8de 5020 ldr.w r5, [lr, #32]
+ 8001242: f002 0707 and.w r7, r2, #7
+ 8001246: 462b mov r3, r5
+ 8001248: 00bf lsls r7, r7, #2
+ 800124a: 250f movs r5, #15
+ 800124c: fa05 f707 lsl.w r7, r5, r7
+ 8001250: ea23 0707 bic.w r7, r3, r7
+ 8001254: f8ce 7020 str.w r7, [lr, #32]
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
+ 8001258: 6887 ldr r7, [r0, #8]
+ 800125a: ea27 0706 bic.w r7, r7, r6
+ 800125e: 6087 str r7, [r0, #8]
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
+ 8001260: 6847 ldr r7, [r0, #4]
+ 8001262: ea27 0708 bic.w r7, r7, r8
+ 8001266: 6047 str r7, [r0, #4]
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
+ 8001268: 68c7 ldr r7, [r0, #12]
+ 800126a: ea27 0606 bic.w r6, r7, r6
+ 800126e: 60c6 str r6, [r0, #12]
+ tmp = SYSCFG->EXTICR[position >> 2];
+ 8001270: f022 0603 bic.w r6, r2, #3
+ 8001274: f106 4680 add.w r6, r6, #1073741824 ; 0x40000000
+ 8001278: f506 3680 add.w r6, r6, #65536 ; 0x10000
+ tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 800127c: f002 0703 and.w r7, r2, #3
+ tmp = SYSCFG->EXTICR[position >> 2];
+ 8001280: f8d6 e008 ldr.w lr, [r6, #8]
+ tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 8001284: 00bf lsls r7, r7, #2
+ 8001286: 40bd lsls r5, r7
+ if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
+ 8001288: f1b0 4f90 cmp.w r0, #1207959552 ; 0x48000000
+ tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
+ 800128c: ea05 0e0e and.w lr, r5, lr
+ if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
+ 8001290: d031 beq.n 80012f6 <HAL_GPIO_DeInit+0xf6>
+ 8001292: 4b21 ldr r3, [pc, #132] ; (8001318 <HAL_GPIO_DeInit+0x118>)
+ 8001294: 4298 cmp r0, r3
+ 8001296: d030 beq.n 80012fa <HAL_GPIO_DeInit+0xfa>
+ 8001298: f503 6380 add.w r3, r3, #1024 ; 0x400
+ 800129c: 4298 cmp r0, r3
+ 800129e: d02e beq.n 80012fe <HAL_GPIO_DeInit+0xfe>
+ 80012a0: f503 6380 add.w r3, r3, #1024 ; 0x400
+ 80012a4: 4298 cmp r0, r3
+ 80012a6: d02c beq.n 8001302 <HAL_GPIO_DeInit+0x102>
+ 80012a8: f503 6380 add.w r3, r3, #1024 ; 0x400
+ 80012ac: 4298 cmp r0, r3
+ 80012ae: d02a beq.n 8001306 <HAL_GPIO_DeInit+0x106>
+ 80012b0: f503 6380 add.w r3, r3, #1024 ; 0x400
+ 80012b4: 4298 cmp r0, r3
+ 80012b6: d028 beq.n 800130a <HAL_GPIO_DeInit+0x10a>
+ 80012b8: 4550 cmp r0, sl
+ 80012ba: d028 beq.n 800130e <HAL_GPIO_DeInit+0x10e>
+ 80012bc: 4558 cmp r0, fp
+ 80012be: bf0c ite eq
+ 80012c0: 2307 moveq r3, #7
+ 80012c2: 2308 movne r3, #8
+ 80012c4: 40bb lsls r3, r7
+ 80012c6: 4573 cmp r3, lr
+ 80012c8: d113 bne.n 80012f2 <HAL_GPIO_DeInit+0xf2>
+ SYSCFG->EXTICR[position >> 2] &= ~tmp;
+ 80012ca: 68b3 ldr r3, [r6, #8]
+ 80012cc: ea23 0505 bic.w r5, r3, r5
+ 80012d0: 60b5 str r5, [r6, #8]
+ EXTI->IMR1 &= ~((uint32_t)iocurrent);
+ 80012d2: 6823 ldr r3, [r4, #0]
+ 80012d4: ea23 030c bic.w r3, r3, ip
+ 80012d8: 6023 str r3, [r4, #0]
+ EXTI->EMR1 &= ~((uint32_t)iocurrent);
+ 80012da: 6863 ldr r3, [r4, #4]
+ 80012dc: ea23 030c bic.w r3, r3, ip
+ 80012e0: 6063 str r3, [r4, #4]
+ EXTI->RTSR1 &= ~((uint32_t)iocurrent);
+ 80012e2: 68a3 ldr r3, [r4, #8]
+ 80012e4: ea23 030c bic.w r3, r3, ip
+ 80012e8: 60a3 str r3, [r4, #8]
+ EXTI->FTSR1 &= ~((uint32_t)iocurrent);
+ 80012ea: 68e3 ldr r3, [r4, #12]
+ 80012ec: ea23 030c bic.w r3, r3, ip
+ 80012f0: 60e3 str r3, [r4, #12]
+ position++;
+ 80012f2: 3201 adds r2, #1
+ 80012f4: e78e b.n 8001214 <HAL_GPIO_DeInit+0x14>
+ if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
+ 80012f6: 2300 movs r3, #0
+ 80012f8: e7e4 b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 80012fa: 2301 movs r3, #1
+ 80012fc: e7e2 b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 80012fe: 2302 movs r3, #2
+ 8001300: e7e0 b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 8001302: 2303 movs r3, #3
+ 8001304: e7de b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 8001306: 2304 movs r3, #4
+ 8001308: e7dc b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 800130a: 2305 movs r3, #5
+ 800130c: e7da b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 800130e: 2306 movs r3, #6
+ 8001310: e7d8 b.n 80012c4 <HAL_GPIO_DeInit+0xc4>
+ 8001312: bf00 nop
+ 8001314: 40010400 .word 0x40010400
+ 8001318: 48000400 .word 0x48000400
+ 800131c: 48001800 .word 0x48001800
+ 8001320: 48001c00 .word 0x48001c00
+
+08001324 <HAL_GPIO_ReadPin>:
+ GPIO_PinState bitstatus;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
+ 8001324: 6903 ldr r3, [r0, #16]
+ 8001326: 4219 tst r1, r3
+ else
+ {
+ bitstatus = GPIO_PIN_RESET;
+ }
+ return bitstatus;
+}
+ 8001328: bf14 ite ne
+ 800132a: 2001 movne r0, #1
+ 800132c: 2000 moveq r0, #0
+ 800132e: 4770 bx lr
+
+08001330 <HAL_GPIO_WritePin>:
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+ assert_param(IS_GPIO_PIN_ACTION(PinState));
+
+ if(PinState != GPIO_PIN_RESET)
+ 8001330: b10a cbz r2, 8001336 <HAL_GPIO_WritePin+0x6>
+ {
+ GPIOx->BSRR = (uint32_t)GPIO_Pin;
+ 8001332: 6181 str r1, [r0, #24]
+ 8001334: 4770 bx lr
+ }
+ else
+ {
+ GPIOx->BRR = (uint32_t)GPIO_Pin;
+ 8001336: 6281 str r1, [r0, #40] ; 0x28
+ }
+}
+ 8001338: 4770 bx lr
+
+0800133a <HAL_GPIO_TogglePin>:
+void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ GPIOx->ODR ^= GPIO_Pin;
+ 800133a: 6943 ldr r3, [r0, #20]
+ 800133c: 4059 eors r1, r3
+ 800133e: 6141 str r1, [r0, #20]
+}
+ 8001340: 4770 bx lr
+
+08001342 <HAL_GPIO_LockPin>:
+ * @param GPIO_Pin: specifies the port bits to be locked.
+ * This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+ 8001342: b082 sub sp, #8
+ __IO uint32_t tmp = GPIO_LCKR_LCKK;
+ 8001344: f44f 3380 mov.w r3, #65536 ; 0x10000
+ 8001348: 9301 str r3, [sp, #4]
+ /* Check the parameters */
+ assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Apply lock key write sequence */
+ tmp |= GPIO_Pin;
+ 800134a: 9b01 ldr r3, [sp, #4]
+ 800134c: 430b orrs r3, r1
+ 800134e: 9301 str r3, [sp, #4]
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ 8001350: 9b01 ldr r3, [sp, #4]
+ 8001352: 61c3 str r3, [r0, #28]
+ /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
+ GPIOx->LCKR = GPIO_Pin;
+ 8001354: 61c1 str r1, [r0, #28]
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ 8001356: 9b01 ldr r3, [sp, #4]
+ 8001358: 61c3 str r3, [r0, #28]
+ /* Read LCKK bit*/
+ tmp = GPIOx->LCKR;
+ 800135a: 69c3 ldr r3, [r0, #28]
+ 800135c: 9301 str r3, [sp, #4]
+
+ if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
+ 800135e: 69c0 ldr r0, [r0, #28]
+ 8001360: f480 3080 eor.w r0, r0, #65536 ; 0x10000
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+ 8001364: f3c0 4000 ubfx r0, r0, #16, #1
+ 8001368: b002 add sp, #8
+ 800136a: 4770 bx lr
+
+0800136c <HAL_GPIO_EXTI_Callback>:
+ UNUSED(GPIO_Pin);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_GPIO_EXTI_Callback could be implemented in the user file
+ */
+}
+ 800136c: 4770 bx lr
+ ...
+
+08001370 <HAL_GPIO_EXTI_IRQHandler>:
+ if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
+ 8001370: 4a04 ldr r2, [pc, #16] ; (8001384 <HAL_GPIO_EXTI_IRQHandler+0x14>)
+ 8001372: 6951 ldr r1, [r2, #20]
+ 8001374: 4201 tst r1, r0
+{
+ 8001376: b508 push {r3, lr}
+ if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
+ 8001378: d002 beq.n 8001380 <HAL_GPIO_EXTI_IRQHandler+0x10>
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
+ 800137a: 6150 str r0, [r2, #20]
+ HAL_GPIO_EXTI_Callback(GPIO_Pin);
+ 800137c: f7ff fff6 bl 800136c <HAL_GPIO_EXTI_Callback>
+}
+ 8001380: bd08 pop {r3, pc}
+ 8001382: bf00 nop
+ 8001384: 40010400 .word 0x40010400
+
+08001388 <SPI_EndRxTxTransaction.isra.0>:
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ __IO uint8_t tmpreg;
+
+ while ((hspi->Instance->SR & Fifo) != State)
+ 8001388: 6803 ldr r3, [r0, #0]
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
+ 800138a: b082 sub sp, #8
+ while ((hspi->Instance->SR & Fifo) != State)
+ 800138c: 689a ldr r2, [r3, #8]
+ 800138e: f412 5fc0 tst.w r2, #6144 ; 0x1800
+ 8001392: d1fb bne.n 800138c <SPI_EndRxTxTransaction.isra.0+0x4>
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, uint32_t State,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 8001394: 689a ldr r2, [r3, #8]
+ 8001396: 0612 lsls r2, r2, #24
+ 8001398: d4fc bmi.n 8001394 <SPI_EndRxTxTransaction.isra.0+0xc>
+ while ((hspi->Instance->SR & Fifo) != State)
+ 800139a: 6898 ldr r0, [r3, #8]
+ 800139c: f410 60c0 ands.w r0, r0, #1536 ; 0x600
+ 80013a0: d101 bne.n 80013a6 <SPI_EndRxTxTransaction.isra.0+0x1e>
+}
+ 80013a2: b002 add sp, #8
+ 80013a4: 4770 bx lr
+ tmpreg = *((__IO uint8_t *)&hspi->Instance->DR);
+ 80013a6: 7b1a ldrb r2, [r3, #12]
+ 80013a8: b2d2 uxtb r2, r2
+ 80013aa: f88d 2007 strb.w r2, [sp, #7]
+ UNUSED(tmpreg);
+ 80013ae: f89d 2007 ldrb.w r2, [sp, #7]
+ 80013b2: e7f2 b.n 800139a <SPI_EndRxTxTransaction.isra.0+0x12>
+
+080013b4 <HAL_SPI_Init>:
+{
+ 80013b4: b5f0 push {r4, r5, r6, r7, lr}
+ if (hspi == NULL)
+ 80013b6: 2800 cmp r0, #0
+ 80013b8: d054 beq.n 8001464 <HAL_SPI_Init+0xb0>
+ if (hspi->State == HAL_SPI_STATE_RESET)
+ 80013ba: f890 305d ldrb.w r3, [r0, #93] ; 0x5d
+ if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
+ 80013be: f8d0 c024 ldr.w ip, [r0, #36] ; 0x24
+ if (hspi->State == HAL_SPI_STATE_RESET)
+ 80013c2: f003 02ff and.w r2, r3, #255 ; 0xff
+ 80013c6: b90b cbnz r3, 80013cc <HAL_SPI_Init+0x18>
+ hspi->Lock = HAL_UNLOCKED;
+ 80013c8: f880 205c strb.w r2, [r0, #92] ; 0x5c
+ __HAL_SPI_DISABLE(hspi);
+ 80013cc: 6801 ldr r1, [r0, #0]
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 80013ce: 68c2 ldr r2, [r0, #12]
+ hspi->State = HAL_SPI_STATE_BUSY;
+ 80013d0: 2302 movs r3, #2
+ 80013d2: f880 305d strb.w r3, [r0, #93] ; 0x5d
+ __HAL_SPI_DISABLE(hspi);
+ 80013d6: 680b ldr r3, [r1, #0]
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 80013d8: f5b2 6fe0 cmp.w r2, #1792 ; 0x700
+ __HAL_SPI_DISABLE(hspi);
+ 80013dc: f023 0340 bic.w r3, r3, #64 ; 0x40
+ 80013e0: 600b str r3, [r1, #0]
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 80013e2: f04f 0300 mov.w r3, #0
+ 80013e6: d83f bhi.n 8001468 <HAL_SPI_Init+0xb4>
+ frxth = SPI_RXFIFO_THRESHOLD_QF;
+ 80013e8: f44f 5580 mov.w r5, #4096 ; 0x1000
+ if ((hspi->Init.DataSize != SPI_DATASIZE_16BIT) && (hspi->Init.DataSize != SPI_DATASIZE_8BIT))
+ 80013ec: d000 beq.n 80013f0 <HAL_SPI_Init+0x3c>
+ hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ 80013ee: 6283 str r3, [r0, #40] ; 0x28
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
+ 80013f0: 6b03 ldr r3, [r0, #48] ; 0x30
+ 80013f2: b92b cbnz r3, 8001400 <HAL_SPI_Init+0x4c>
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 80013f4: f5b2 6fe0 cmp.w r2, #1792 ; 0x700
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
+ 80013f8: bf8c ite hi
+ 80013fa: 2302 movhi r3, #2
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
+ 80013fc: 2301 movls r3, #1
+ 80013fe: 6303 str r3, [r0, #48] ; 0x30
+ WRITE_REG(hspi->Instance->CR1, (hspi->Init.Mode | hspi->Init.Direction |
+ 8001400: e9d0 3701 ldrd r3, r7, [r0, #4]
+ 8001404: 433b orrs r3, r7
+ 8001406: 6907 ldr r7, [r0, #16]
+ 8001408: 6984 ldr r4, [r0, #24]
+ 800140a: 6a86 ldr r6, [r0, #40] ; 0x28
+ 800140c: 433b orrs r3, r7
+ 800140e: 6947 ldr r7, [r0, #20]
+ 8001410: 433b orrs r3, r7
+ 8001412: 69c7 ldr r7, [r0, #28]
+ 8001414: 433b orrs r3, r7
+ 8001416: 6a07 ldr r7, [r0, #32]
+ 8001418: 433b orrs r3, r7
+ 800141a: 4333 orrs r3, r6
+ 800141c: f404 7700 and.w r7, r4, #512 ; 0x200
+ 8001420: 433b orrs r3, r7
+ 8001422: 600b str r3, [r1, #0]
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ 8001424: 6b03 ldr r3, [r0, #48] ; 0x30
+ 8001426: 2b02 cmp r3, #2
+ hspi->Instance->CR1 |= SPI_CR1_CRCL;
+ 8001428: bf02 ittt eq
+ 800142a: 680b ldreq r3, [r1, #0]
+ 800142c: f443 6300 orreq.w r3, r3, #2048 ; 0x800
+ 8001430: 600b streq r3, [r1, #0]
+ WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) | hspi->Init.TIMode |
+ 8001432: 6b43 ldr r3, [r0, #52] ; 0x34
+ 8001434: ea4c 0202 orr.w r2, ip, r2
+ 8001438: 0c24 lsrs r4, r4, #16
+ 800143a: 431a orrs r2, r3
+ 800143c: f004 0404 and.w r4, r4, #4
+ 8001440: 4322 orrs r2, r4
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 8001442: f5b6 5f00 cmp.w r6, #8192 ; 0x2000
+ WRITE_REG(hspi->Instance->CRCPR, hspi->Init.CRCPolynomial);
+ 8001446: bf08 it eq
+ 8001448: 6ac3 ldreq r3, [r0, #44] ; 0x2c
+ WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) | hspi->Init.TIMode |
+ 800144a: ea45 0502 orr.w r5, r5, r2
+ 800144e: 604d str r5, [r1, #4]
+ hspi->State = HAL_SPI_STATE_READY;
+ 8001450: f04f 0201 mov.w r2, #1
+ WRITE_REG(hspi->Instance->CRCPR, hspi->Init.CRCPolynomial);
+ 8001454: bf08 it eq
+ 8001456: 610b streq r3, [r1, #16]
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 8001458: 2300 movs r3, #0
+ 800145a: 6603 str r3, [r0, #96] ; 0x60
+ hspi->State = HAL_SPI_STATE_READY;
+ 800145c: f880 205d strb.w r2, [r0, #93] ; 0x5d
+ return HAL_OK;
+ 8001460: 4618 mov r0, r3
+}
+ 8001462: bdf0 pop {r4, r5, r6, r7, pc}
+ return HAL_ERROR;
+ 8001464: 2001 movs r0, #1
+ 8001466: e7fc b.n 8001462 <HAL_SPI_Init+0xae>
+ frxth = SPI_RXFIFO_THRESHOLD_HF;
+ 8001468: 461d mov r5, r3
+ if ((hspi->Init.DataSize != SPI_DATASIZE_16BIT) && (hspi->Init.DataSize != SPI_DATASIZE_8BIT))
+ 800146a: f5b2 6f70 cmp.w r2, #3840 ; 0xf00
+ 800146e: e7bd b.n 80013ec <HAL_SPI_Init+0x38>
+
+08001470 <HAL_SPI_Transmit>:
+{
+ 8001470: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr}
+ 8001474: 461e mov r6, r3
+ __HAL_LOCK(hspi);
+ 8001476: f890 305c ldrb.w r3, [r0, #92] ; 0x5c
+ 800147a: 2b01 cmp r3, #1
+{
+ 800147c: 4604 mov r4, r0
+ 800147e: 460d mov r5, r1
+ 8001480: 4690 mov r8, r2
+ __HAL_LOCK(hspi);
+ 8001482: f000 809c beq.w 80015be <HAL_SPI_Transmit+0x14e>
+ 8001486: 2301 movs r3, #1
+ 8001488: f880 305c strb.w r3, [r0, #92] ; 0x5c
+ tickstart = HAL_GetTick();
+ 800148c: f005 fe60 bl 8007150 <HAL_GetTick>
+ if (hspi->State != HAL_SPI_STATE_READY)
+ 8001490: f894 305d ldrb.w r3, [r4, #93] ; 0x5d
+ 8001494: 2b01 cmp r3, #1
+ tickstart = HAL_GetTick();
+ 8001496: 4607 mov r7, r0
+ if (hspi->State != HAL_SPI_STATE_READY)
+ 8001498: b2d8 uxtb r0, r3
+ 800149a: f040 808e bne.w 80015ba <HAL_SPI_Transmit+0x14a>
+ if ((pData == NULL) || (Size == 0U))
+ 800149e: 2d00 cmp r5, #0
+ 80014a0: d07a beq.n 8001598 <HAL_SPI_Transmit+0x128>
+ 80014a2: f1b8 0f00 cmp.w r8, #0
+ 80014a6: d077 beq.n 8001598 <HAL_SPI_Transmit+0x128>
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ 80014a8: 2303 movs r3, #3
+ 80014aa: f884 305d strb.w r3, [r4, #93] ; 0x5d
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 80014ae: 68a3 ldr r3, [r4, #8]
+ SPI_1LINE_TX(hspi);
+ 80014b0: 6822 ldr r2, [r4, #0]
+ hspi->pTxBuffPtr = (uint8_t *)pData;
+ 80014b2: 63a5 str r5, [r4, #56] ; 0x38
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 80014b4: 2100 movs r1, #0
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 80014b6: f5b3 4f00 cmp.w r3, #32768 ; 0x8000
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 80014ba: 6621 str r1, [r4, #96] ; 0x60
+ hspi->TxXferCount = Size;
+ 80014bc: f8a4 803e strh.w r8, [r4, #62] ; 0x3e
+ hspi->RxXferCount = 0U;
+ 80014c0: f8a4 1046 strh.w r1, [r4, #70] ; 0x46
+ SPI_1LINE_TX(hspi);
+ 80014c4: bf08 it eq
+ 80014c6: 6813 ldreq r3, [r2, #0]
+ hspi->TxXferSize = Size;
+ 80014c8: f8a4 803c strh.w r8, [r4, #60] ; 0x3c
+ SPI_1LINE_TX(hspi);
+ 80014cc: bf08 it eq
+ 80014ce: f443 4380 orreq.w r3, r3, #16384 ; 0x4000
+ hspi->RxISR = NULL;
+ 80014d2: e9c4 1113 strd r1, r1, [r4, #76] ; 0x4c
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ 80014d6: 6421 str r1, [r4, #64] ; 0x40
+ hspi->RxXferSize = 0U;
+ 80014d8: f8a4 1044 strh.w r1, [r4, #68] ; 0x44
+ SPI_1LINE_TX(hspi);
+ 80014dc: bf08 it eq
+ 80014de: 6013 streq r3, [r2, #0]
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 80014e0: 6aa3 ldr r3, [r4, #40] ; 0x28
+ 80014e2: f5b3 5f00 cmp.w r3, #8192 ; 0x2000
+ 80014e6: d107 bne.n 80014f8 <HAL_SPI_Transmit+0x88>
+ SPI_RESET_CRC(hspi);
+ 80014e8: 6813 ldr r3, [r2, #0]
+ 80014ea: f423 5300 bic.w r3, r3, #8192 ; 0x2000
+ 80014ee: 6013 str r3, [r2, #0]
+ 80014f0: 6813 ldr r3, [r2, #0]
+ 80014f2: f443 5300 orr.w r3, r3, #8192 ; 0x2000
+ 80014f6: 6013 str r3, [r2, #0]
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ 80014f8: 6813 ldr r3, [r2, #0]
+ 80014fa: 0659 lsls r1, r3, #25
+ __HAL_SPI_ENABLE(hspi);
+ 80014fc: bf5e ittt pl
+ 80014fe: 6813 ldrpl r3, [r2, #0]
+ 8001500: f043 0340 orrpl.w r3, r3, #64 ; 0x40
+ 8001504: 6013 strpl r3, [r2, #0]
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
+ 8001506: 6863 ldr r3, [r4, #4]
+ 8001508: b11b cbz r3, 8001512 <HAL_SPI_Transmit+0xa2>
+ 800150a: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 800150c: b29b uxth r3, r3
+ 800150e: 2b01 cmp r3, #1
+ 8001510: d110 bne.n 8001534 <HAL_SPI_Transmit+0xc4>
+ if (hspi->TxXferCount > 1U)
+ 8001512: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 8001514: b29b uxth r3, r3
+ 8001516: 2b01 cmp r3, #1
+ 8001518: d905 bls.n 8001526 <HAL_SPI_Transmit+0xb6>
+ hspi->Instance->DR = *((uint16_t *)pData);
+ 800151a: f835 3b02 ldrh.w r3, [r5], #2
+ 800151e: 60d3 str r3, [r2, #12]
+ hspi->TxXferCount -= 2U;
+ 8001520: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 8001522: 3b02 subs r3, #2
+ 8001524: e004 b.n 8001530 <HAL_SPI_Transmit+0xc0>
+ *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
+ 8001526: f815 3b01 ldrb.w r3, [r5], #1
+ 800152a: 7313 strb r3, [r2, #12]
+ hspi->TxXferCount--;
+ 800152c: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 800152e: 3b01 subs r3, #1
+ 8001530: b29b uxth r3, r3
+ 8001532: 87e3 strh r3, [r4, #62] ; 0x3e
+ while (hspi->TxXferCount > 0U)
+ 8001534: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 8001536: b29b uxth r3, r3
+ 8001538: b9e3 cbnz r3, 8001574 <HAL_SPI_Transmit+0x104>
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 800153a: 6aa3 ldr r3, [r4, #40] ; 0x28
+ 800153c: f5b3 5f00 cmp.w r3, #8192 ; 0x2000
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ 8001540: bf01 itttt eq
+ 8001542: 6822 ldreq r2, [r4, #0]
+ 8001544: 6813 ldreq r3, [r2, #0]
+ 8001546: f443 5380 orreq.w r3, r3, #4096 ; 0x1000
+ 800154a: 6013 streq r3, [r2, #0]
+ if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+ 800154c: 4620 mov r0, r4
+ 800154e: f7ff ff1b bl 8001388 <SPI_EndRxTxTransaction.isra.0>
+ 8001552: b108 cbz r0, 8001558 <HAL_SPI_Transmit+0xe8>
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ 8001554: 2320 movs r3, #32
+ 8001556: 6623 str r3, [r4, #96] ; 0x60
+ if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ 8001558: 68a3 ldr r3, [r4, #8]
+ 800155a: b933 cbnz r3, 800156a <HAL_SPI_Transmit+0xfa>
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ 800155c: 9301 str r3, [sp, #4]
+ 800155e: 6823 ldr r3, [r4, #0]
+ 8001560: 68da ldr r2, [r3, #12]
+ 8001562: 9201 str r2, [sp, #4]
+ 8001564: 689b ldr r3, [r3, #8]
+ 8001566: 9301 str r3, [sp, #4]
+ 8001568: 9b01 ldr r3, [sp, #4]
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ 800156a: 6e20 ldr r0, [r4, #96] ; 0x60
+ errorcode = HAL_BUSY;
+ 800156c: 3800 subs r0, #0
+ 800156e: bf18 it ne
+ 8001570: 2001 movne r0, #1
+error:
+ 8001572: e011 b.n 8001598 <HAL_SPI_Transmit+0x128>
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
+ 8001574: 6823 ldr r3, [r4, #0]
+ 8001576: 689a ldr r2, [r3, #8]
+ 8001578: 0792 lsls r2, r2, #30
+ 800157a: d50b bpl.n 8001594 <HAL_SPI_Transmit+0x124>
+ if (hspi->TxXferCount > 1U)
+ 800157c: 8fe2 ldrh r2, [r4, #62] ; 0x3e
+ 800157e: b292 uxth r2, r2
+ 8001580: 2a01 cmp r2, #1
+ 8001582: d903 bls.n 800158c <HAL_SPI_Transmit+0x11c>
+ hspi->Instance->DR = *((uint16_t *)pData);
+ 8001584: f835 2b02 ldrh.w r2, [r5], #2
+ 8001588: 60da str r2, [r3, #12]
+ 800158a: e7c9 b.n 8001520 <HAL_SPI_Transmit+0xb0>
+ *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
+ 800158c: f815 2b01 ldrb.w r2, [r5], #1
+ 8001590: 731a strb r2, [r3, #12]
+ hspi->TxXferCount--;
+ 8001592: e7cb b.n 800152c <HAL_SPI_Transmit+0xbc>
+ if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))
+ 8001594: b94e cbnz r6, 80015aa <HAL_SPI_Transmit+0x13a>
+ errorcode = HAL_TIMEOUT;
+ 8001596: 2003 movs r0, #3
+ hspi->State = HAL_SPI_STATE_READY;
+ 8001598: 2301 movs r3, #1
+ 800159a: f884 305d strb.w r3, [r4, #93] ; 0x5d
+ __HAL_UNLOCK(hspi);
+ 800159e: 2300 movs r3, #0
+ 80015a0: f884 305c strb.w r3, [r4, #92] ; 0x5c
+}
+ 80015a4: b002 add sp, #8
+ 80015a6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc}
+ if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))
+ 80015aa: 1c73 adds r3, r6, #1
+ 80015ac: d0c2 beq.n 8001534 <HAL_SPI_Transmit+0xc4>
+ 80015ae: f005 fdcf bl 8007150 <HAL_GetTick>
+ 80015b2: 1bc0 subs r0, r0, r7
+ 80015b4: 42b0 cmp r0, r6
+ 80015b6: d3bd bcc.n 8001534 <HAL_SPI_Transmit+0xc4>
+ 80015b8: e7ed b.n 8001596 <HAL_SPI_Transmit+0x126>
+ errorcode = HAL_BUSY;
+ 80015ba: 2002 movs r0, #2
+ 80015bc: e7ec b.n 8001598 <HAL_SPI_Transmit+0x128>
+ __HAL_LOCK(hspi);
+ 80015be: 2002 movs r0, #2
+ 80015c0: e7f0 b.n 80015a4 <HAL_SPI_Transmit+0x134>
+
+080015c2 <HAL_SPI_TransmitReceive>:
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
+ uint32_t Timeout)
+{
+ 80015c2: e92d 43f7 stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, lr}
+ 80015c6: 461e mov r6, r3
+ uint32_t tmp = 0U, tmp1 = 0U;
+#if (USE_SPI_CRC != 0U)
+ __IO uint16_t tmpreg = 0U;
+ 80015c8: 2300 movs r3, #0
+ 80015ca: f8ad 3006 strh.w r3, [sp, #6]
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+ 80015ce: f890 305c ldrb.w r3, [r0, #92] ; 0x5c
+{
+ 80015d2: f8dd 8028 ldr.w r8, [sp, #40] ; 0x28
+ __HAL_LOCK(hspi);
+ 80015d6: 2b01 cmp r3, #1
+{
+ 80015d8: 4604 mov r4, r0
+ 80015da: 460d mov r5, r1
+ 80015dc: 4617 mov r7, r2
+ __HAL_LOCK(hspi);
+ 80015de: f000 8124 beq.w 800182a <HAL_SPI_TransmitReceive+0x268>
+ 80015e2: 2301 movs r3, #1
+ 80015e4: f880 305c strb.w r3, [r0, #92] ; 0x5c
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ 80015e8: f005 fdb2 bl 8007150 <HAL_GetTick>
+
+ tmp = hspi->State;
+ 80015ec: f894 305d ldrb.w r3, [r4, #93] ; 0x5d
+ tmp1 = hspi->Init.Mode;
+ 80015f0: 6861 ldr r1, [r4, #4]
+
+ if (!((tmp == HAL_SPI_STATE_READY) || \
+ 80015f2: 2b01 cmp r3, #1
+ tickstart = HAL_GetTick();
+ 80015f4: 4681 mov r9, r0
+ tmp = hspi->State;
+ 80015f6: b2da uxtb r2, r3
+ if (!((tmp == HAL_SPI_STATE_READY) || \
+ 80015f8: d00a beq.n 8001610 <HAL_SPI_TransmitReceive+0x4e>
+ 80015fa: f5b1 7f82 cmp.w r1, #260 ; 0x104
+ 80015fe: f040 8112 bne.w 8001826 <HAL_SPI_TransmitReceive+0x264>
+ ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX))))
+ 8001602: 68a3 ldr r3, [r4, #8]
+ 8001604: 2b00 cmp r3, #0
+ 8001606: f040 810e bne.w 8001826 <HAL_SPI_TransmitReceive+0x264>
+ 800160a: 2a04 cmp r2, #4
+ 800160c: f040 810b bne.w 8001826 <HAL_SPI_TransmitReceive+0x264>
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ 8001610: b955 cbnz r5, 8001628 <HAL_SPI_TransmitReceive+0x66>
+ {
+ errorcode = HAL_ERROR;
+ 8001612: 2101 movs r1, #1
+ {
+ errorcode = HAL_ERROR;
+ }
+
+error :
+ hspi->State = HAL_SPI_STATE_READY;
+ 8001614: 2301 movs r3, #1
+ 8001616: f884 305d strb.w r3, [r4, #93] ; 0x5d
+ __HAL_UNLOCK(hspi);
+ 800161a: 2300 movs r3, #0
+ 800161c: f884 305c strb.w r3, [r4, #92] ; 0x5c
+ return errorcode;
+}
+ 8001620: 4608 mov r0, r1
+ 8001622: b003 add sp, #12
+ 8001624: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc}
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ 8001628: 2f00 cmp r7, #0
+ 800162a: d0f2 beq.n 8001612 <HAL_SPI_TransmitReceive+0x50>
+ 800162c: 2e00 cmp r6, #0
+ 800162e: d0f0 beq.n 8001612 <HAL_SPI_TransmitReceive+0x50>
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ 8001630: f894 305d ldrb.w r3, [r4, #93] ; 0x5d
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 8001634: 6aa2 ldr r2, [r4, #40] ; 0x28
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ 8001636: 6427 str r7, [r4, #64] ; 0x40
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ 8001638: 2b04 cmp r3, #4
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ 800163a: bf1c itt ne
+ 800163c: 2305 movne r3, #5
+ 800163e: f884 305d strbne.w r3, [r4, #93] ; 0x5d
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 8001642: 2300 movs r3, #0
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 8001644: f5b2 5f00 cmp.w r2, #8192 ; 0x2000
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 8001648: 6623 str r3, [r4, #96] ; 0x60
+ hspi->TxISR = NULL;
+ 800164a: e9c4 3313 strd r3, r3, [r4, #76] ; 0x4c
+ hspi->RxXferCount = Size;
+ 800164e: f8a4 6046 strh.w r6, [r4, #70] ; 0x46
+ SPI_RESET_CRC(hspi);
+ 8001652: 6823 ldr r3, [r4, #0]
+ hspi->RxXferSize = Size;
+ 8001654: f8a4 6044 strh.w r6, [r4, #68] ; 0x44
+ hspi->pTxBuffPtr = (uint8_t *)pTxData;
+ 8001658: 63a5 str r5, [r4, #56] ; 0x38
+ hspi->TxXferCount = Size;
+ 800165a: 87e6 strh r6, [r4, #62] ; 0x3e
+ hspi->TxXferSize = Size;
+ 800165c: 87a6 strh r6, [r4, #60] ; 0x3c
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 800165e: d107 bne.n 8001670 <HAL_SPI_TransmitReceive+0xae>
+ SPI_RESET_CRC(hspi);
+ 8001660: 681a ldr r2, [r3, #0]
+ 8001662: f422 5200 bic.w r2, r2, #8192 ; 0x2000
+ 8001666: 601a str r2, [r3, #0]
+ 8001668: 681a ldr r2, [r3, #0]
+ 800166a: f442 5200 orr.w r2, r2, #8192 ; 0x2000
+ 800166e: 601a str r2, [r3, #0]
+ if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U))
+ 8001670: 68e2 ldr r2, [r4, #12]
+ 8001672: f5b2 6fe0 cmp.w r2, #1792 ; 0x700
+ 8001676: d804 bhi.n 8001682 <HAL_SPI_TransmitReceive+0xc0>
+ 8001678: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46
+ 800167c: b292 uxth r2, r2
+ 800167e: 2a01 cmp r2, #1
+ 8001680: d94e bls.n 8001720 <HAL_SPI_TransmitReceive+0x15e>
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 8001682: 685a ldr r2, [r3, #4]
+ 8001684: f422 5280 bic.w r2, r2, #4096 ; 0x1000
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 8001688: 605a str r2, [r3, #4]
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ 800168a: 681a ldr r2, [r3, #0]
+ 800168c: 0650 lsls r0, r2, #25
+ __HAL_SPI_ENABLE(hspi);
+ 800168e: bf5e ittt pl
+ 8001690: 681a ldrpl r2, [r3, #0]
+ 8001692: f042 0240 orrpl.w r2, r2, #64 ; 0x40
+ 8001696: 601a strpl r2, [r3, #0]
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
+ 8001698: b119 cbz r1, 80016a2 <HAL_SPI_TransmitReceive+0xe0>
+ 800169a: 8fe2 ldrh r2, [r4, #62] ; 0x3e
+ 800169c: b292 uxth r2, r2
+ 800169e: 2a01 cmp r2, #1
+ 80016a0: d10a bne.n 80016b8 <HAL_SPI_TransmitReceive+0xf6>
+ if (hspi->TxXferCount > 1U)
+ 80016a2: 8fe2 ldrh r2, [r4, #62] ; 0x3e
+ 80016a4: b292 uxth r2, r2
+ 80016a6: 2a01 cmp r2, #1
+ 80016a8: d93e bls.n 8001728 <HAL_SPI_TransmitReceive+0x166>
+ hspi->Instance->DR = *((uint16_t *)pTxData);
+ 80016aa: f835 2b02 ldrh.w r2, [r5], #2
+ 80016ae: 60da str r2, [r3, #12]
+ hspi->TxXferCount -= 2U;
+ 80016b0: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 80016b2: 3b02 subs r3, #2
+ 80016b4: b29b uxth r3, r3
+ 80016b6: 87e3 strh r3, [r4, #62] ; 0x3e
+ txallowed = 1U;
+ 80016b8: 2601 movs r6, #1
+ while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
+ 80016ba: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 80016bc: b29b uxth r3, r3
+ 80016be: 2b00 cmp r3, #0
+ 80016c0: d138 bne.n 8001734 <HAL_SPI_TransmitReceive+0x172>
+ 80016c2: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46
+ 80016c6: b29b uxth r3, r3
+ 80016c8: 2b00 cmp r3, #0
+ 80016ca: d133 bne.n 8001734 <HAL_SPI_TransmitReceive+0x172>
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 80016cc: 6aa2 ldr r2, [r4, #40] ; 0x28
+ if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
+ 80016ce: 6823 ldr r3, [r4, #0]
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 80016d0: f5b2 5f00 cmp.w r2, #8192 ; 0x2000
+ 80016d4: d10d bne.n 80016f2 <HAL_SPI_TransmitReceive+0x130>
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 80016d6: 689a ldr r2, [r3, #8]
+ 80016d8: 07d1 lsls r1, r2, #31
+ 80016da: d5fc bpl.n 80016d6 <HAL_SPI_TransmitReceive+0x114>
+ if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ 80016dc: 68e2 ldr r2, [r4, #12]
+ 80016de: f5b2 6f70 cmp.w r2, #3840 ; 0xf00
+ 80016e2: f040 8092 bne.w 800180a <HAL_SPI_TransmitReceive+0x248>
+ tmpreg = hspi->Instance->DR;
+ 80016e6: 68da ldr r2, [r3, #12]
+ 80016e8: b292 uxth r2, r2
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 80016ea: f8ad 2006 strh.w r2, [sp, #6]
+ UNUSED(tmpreg);
+ 80016ee: f8bd 2006 ldrh.w r2, [sp, #6]
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ 80016f2: 6899 ldr r1, [r3, #8]
+ 80016f4: f011 0110 ands.w r1, r1, #16
+ 80016f8: d007 beq.n 800170a <HAL_SPI_TransmitReceive+0x148>
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ 80016fa: 6e22 ldr r2, [r4, #96] ; 0x60
+ 80016fc: f042 0202 orr.w r2, r2, #2
+ 8001700: 6622 str r2, [r4, #96] ; 0x60
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ 8001702: f64f 72ef movw r2, #65519 ; 0xffef
+ 8001706: 609a str r2, [r3, #8]
+ errorcode = HAL_ERROR;
+ 8001708: 2101 movs r1, #1
+ if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+ 800170a: 4620 mov r0, r4
+ 800170c: f7ff fe3c bl 8001388 <SPI_EndRxTxTransaction.isra.0>
+ 8001710: b108 cbz r0, 8001716 <HAL_SPI_TransmitReceive+0x154>
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ 8001712: 2320 movs r3, #32
+ 8001714: 6623 str r3, [r4, #96] ; 0x60
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ 8001716: 6e23 ldr r3, [r4, #96] ; 0x60
+ 8001718: 2b00 cmp r3, #0
+ 800171a: f47f af7a bne.w 8001612 <HAL_SPI_TransmitReceive+0x50>
+ 800171e: e779 b.n 8001614 <HAL_SPI_TransmitReceive+0x52>
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 8001720: 685a ldr r2, [r3, #4]
+ 8001722: f442 5280 orr.w r2, r2, #4096 ; 0x1000
+ 8001726: e7af b.n 8001688 <HAL_SPI_TransmitReceive+0xc6>
+ *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
+ 8001728: f815 2b01 ldrb.w r2, [r5], #1
+ 800172c: 731a strb r2, [r3, #12]
+ hspi->TxXferCount--;
+ 800172e: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 8001730: 3b01 subs r3, #1
+ 8001732: e7bf b.n 80016b4 <HAL_SPI_TransmitReceive+0xf2>
+ if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
+ 8001734: 2e00 cmp r6, #0
+ 8001736: d030 beq.n 800179a <HAL_SPI_TransmitReceive+0x1d8>
+ 8001738: 8fe3 ldrh r3, [r4, #62] ; 0x3e
+ 800173a: b29b uxth r3, r3
+ 800173c: 2b00 cmp r3, #0
+ 800173e: d02c beq.n 800179a <HAL_SPI_TransmitReceive+0x1d8>
+ 8001740: 6823 ldr r3, [r4, #0]
+ 8001742: 689a ldr r2, [r3, #8]
+ 8001744: 0792 lsls r2, r2, #30
+ 8001746: d528 bpl.n 800179a <HAL_SPI_TransmitReceive+0x1d8>
+ if (hspi->TxXferCount > 1U)
+ 8001748: 8fe2 ldrh r2, [r4, #62] ; 0x3e
+ 800174a: b292 uxth r2, r2
+ 800174c: 2a01 cmp r2, #1
+ hspi->Instance->DR = *((uint16_t *)pTxData);
+ 800174e: bf8b itete hi
+ 8001750: f835 2b02 ldrhhi.w r2, [r5], #2
+ *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
+ 8001754: f815 2b01 ldrbls.w r2, [r5], #1
+ hspi->Instance->DR = *((uint16_t *)pTxData);
+ 8001758: 60da strhi r2, [r3, #12]
+ *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
+ 800175a: 731a strbls r2, [r3, #12]
+ hspi->TxXferCount -= 2U;
+ 800175c: bf8b itete hi
+ 800175e: 8fe3 ldrhhi r3, [r4, #62] ; 0x3e
+ hspi->TxXferCount--;
+ 8001760: 8fe3 ldrhls r3, [r4, #62] ; 0x3e
+ hspi->TxXferCount -= 2U;
+ 8001762: 3b02 subhi r3, #2
+ hspi->TxXferCount--;
+ 8001764: f103 33ff addls.w r3, r3, #4294967295 ; 0xffffffff
+ 8001768: b29b uxth r3, r3
+ 800176a: 87e3 strh r3, [r4, #62] ; 0x3e
+ if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ 800176c: 8fe6 ldrh r6, [r4, #62] ; 0x3e
+ 800176e: b2b6 uxth r6, r6
+ 8001770: b996 cbnz r6, 8001798 <HAL_SPI_TransmitReceive+0x1d6>
+ 8001772: 6aa3 ldr r3, [r4, #40] ; 0x28
+ 8001774: f5b3 5f00 cmp.w r3, #8192 ; 0x2000
+ 8001778: d10f bne.n 800179a <HAL_SPI_TransmitReceive+0x1d8>
+ if (((hspi->Instance->CR1 & SPI_CR1_MSTR) == 0U) && ((hspi->Instance->CR2 & SPI_CR2_NSSP) == SPI_CR2_NSSP))
+ 800177a: 6823 ldr r3, [r4, #0]
+ 800177c: 681a ldr r2, [r3, #0]
+ 800177e: 0756 lsls r6, r2, #29
+ 8001780: d406 bmi.n 8001790 <HAL_SPI_TransmitReceive+0x1ce>
+ 8001782: 685a ldr r2, [r3, #4]
+ 8001784: 0710 lsls r0, r2, #28
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+ 8001786: bf42 ittt mi
+ 8001788: 681a ldrmi r2, [r3, #0]
+ 800178a: f442 7200 orrmi.w r2, r2, #512 ; 0x200
+ 800178e: 601a strmi r2, [r3, #0]
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ 8001790: 681a ldr r2, [r3, #0]
+ 8001792: f442 5280 orr.w r2, r2, #4096 ; 0x1000
+ 8001796: 601a str r2, [r3, #0]
+ txallowed = 0U;
+ 8001798: 2600 movs r6, #0
+ if ((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)))
+ 800179a: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46
+ 800179e: b29b uxth r3, r3
+ 80017a0: b1e3 cbz r3, 80017dc <HAL_SPI_TransmitReceive+0x21a>
+ 80017a2: 6821 ldr r1, [r4, #0]
+ 80017a4: 688b ldr r3, [r1, #8]
+ 80017a6: f013 0301 ands.w r3, r3, #1
+ 80017aa: d017 beq.n 80017dc <HAL_SPI_TransmitReceive+0x21a>
+ if (hspi->RxXferCount > 1U)
+ 80017ac: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46
+ 80017b0: b292 uxth r2, r2
+ 80017b2: 2a01 cmp r2, #1
+ 80017b4: d91f bls.n 80017f6 <HAL_SPI_TransmitReceive+0x234>
+ *((uint16_t *)pRxData) = hspi->Instance->DR;
+ 80017b6: 68ca ldr r2, [r1, #12]
+ 80017b8: f827 2b02 strh.w r2, [r7], #2
+ hspi->RxXferCount -= 2U;
+ 80017bc: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46
+ 80017c0: 3a02 subs r2, #2
+ 80017c2: b292 uxth r2, r2
+ 80017c4: f8a4 2046 strh.w r2, [r4, #70] ; 0x46
+ if (hspi->RxXferCount <= 1U)
+ 80017c8: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46
+ 80017cc: b292 uxth r2, r2
+ 80017ce: 2a01 cmp r2, #1
+ 80017d0: d803 bhi.n 80017da <HAL_SPI_TransmitReceive+0x218>
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 80017d2: 684a ldr r2, [r1, #4]
+ 80017d4: f442 5280 orr.w r2, r2, #4096 ; 0x1000
+ 80017d8: 604a str r2, [r1, #4]
+ txallowed = 1U;
+ 80017da: 461e mov r6, r3
+ if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))
+ 80017dc: f1b8 3fff cmp.w r8, #4294967295 ; 0xffffffff
+ 80017e0: f43f af6b beq.w 80016ba <HAL_SPI_TransmitReceive+0xf8>
+ 80017e4: f005 fcb4 bl 8007150 <HAL_GetTick>
+ 80017e8: eba0 0009 sub.w r0, r0, r9
+ 80017ec: 4540 cmp r0, r8
+ 80017ee: f4ff af64 bcc.w 80016ba <HAL_SPI_TransmitReceive+0xf8>
+ errorcode = HAL_TIMEOUT;
+ 80017f2: 2103 movs r1, #3
+ 80017f4: e70e b.n 8001614 <HAL_SPI_TransmitReceive+0x52>
+ (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR;
+ 80017f6: 7b0a ldrb r2, [r1, #12]
+ 80017f8: f807 2b01 strb.w r2, [r7], #1
+ hspi->RxXferCount--;
+ 80017fc: f8b4 1046 ldrh.w r1, [r4, #70] ; 0x46
+ 8001800: 3901 subs r1, #1
+ 8001802: b289 uxth r1, r1
+ 8001804: f8a4 1046 strh.w r1, [r4, #70] ; 0x46
+ 8001808: e7e7 b.n 80017da <HAL_SPI_TransmitReceive+0x218>
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 800180a: 7b1a ldrb r2, [r3, #12]
+ 800180c: f8ad 2006 strh.w r2, [sp, #6]
+ UNUSED(tmpreg);
+ 8001810: f8bd 2006 ldrh.w r2, [sp, #6]
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ 8001814: 6b22 ldr r2, [r4, #48] ; 0x30
+ 8001816: 2a02 cmp r2, #2
+ 8001818: f47f af6b bne.w 80016f2 <HAL_SPI_TransmitReceive+0x130>
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 800181c: 689a ldr r2, [r3, #8]
+ 800181e: 07d2 lsls r2, r2, #31
+ 8001820: d5fc bpl.n 800181c <HAL_SPI_TransmitReceive+0x25a>
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 8001822: 7b1a ldrb r2, [r3, #12]
+ 8001824: e761 b.n 80016ea <HAL_SPI_TransmitReceive+0x128>
+ errorcode = HAL_BUSY;
+ 8001826: 2102 movs r1, #2
+ 8001828: e6f4 b.n 8001614 <HAL_SPI_TransmitReceive+0x52>
+ __HAL_LOCK(hspi);
+ 800182a: 2102 movs r1, #2
+ 800182c: e6f8 b.n 8001620 <HAL_SPI_TransmitReceive+0x5e>
+
+0800182e <HAL_SPI_Receive>:
+{
+ 800182e: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
+ 8001832: 461f mov r7, r3
+ __IO uint16_t tmpreg = 0U;
+ 8001834: 2300 movs r3, #0
+ 8001836: f8ad 300e strh.w r3, [sp, #14]
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ 800183a: 6843 ldr r3, [r0, #4]
+ 800183c: f5b3 7f82 cmp.w r3, #260 ; 0x104
+{
+ 8001840: 4604 mov r4, r0
+ 8001842: 460e mov r6, r1
+ 8001844: 4615 mov r5, r2
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ 8001846: d10c bne.n 8001862 <HAL_SPI_Receive+0x34>
+ 8001848: 6883 ldr r3, [r0, #8]
+ 800184a: b953 cbnz r3, 8001862 <HAL_SPI_Receive+0x34>
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ 800184c: 2304 movs r3, #4
+ 800184e: f880 305d strb.w r3, [r0, #93] ; 0x5d
+ return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
+ 8001852: 4613 mov r3, r2
+ 8001854: 9700 str r7, [sp, #0]
+ 8001856: 460a mov r2, r1
+ 8001858: f7ff feb3 bl 80015c2 <HAL_SPI_TransmitReceive>
+}
+ 800185c: b004 add sp, #16
+ 800185e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc}
+ __HAL_LOCK(hspi);
+ 8001862: f894 305c ldrb.w r3, [r4, #92] ; 0x5c
+ 8001866: 2b01 cmp r3, #1
+ 8001868: f000 80dd beq.w 8001a26 <HAL_SPI_Receive+0x1f8>
+ 800186c: 2301 movs r3, #1
+ 800186e: f884 305c strb.w r3, [r4, #92] ; 0x5c
+ tickstart = HAL_GetTick();
+ 8001872: f005 fc6d bl 8007150 <HAL_GetTick>
+ if (hspi->State != HAL_SPI_STATE_READY)
+ 8001876: f894 305d ldrb.w r3, [r4, #93] ; 0x5d
+ 800187a: 2b01 cmp r3, #1
+ tickstart = HAL_GetTick();
+ 800187c: 4680 mov r8, r0
+ if (hspi->State != HAL_SPI_STATE_READY)
+ 800187e: b2d8 uxtb r0, r3
+ 8001880: f040 80cf bne.w 8001a22 <HAL_SPI_Receive+0x1f4>
+ if ((pData == NULL) || (Size == 0U))
+ 8001884: 2e00 cmp r6, #0
+ 8001886: f000 8092 beq.w 80019ae <HAL_SPI_Receive+0x180>
+ 800188a: 2d00 cmp r5, #0
+ 800188c: f000 808f beq.w 80019ae <HAL_SPI_Receive+0x180>
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ 8001890: 2304 movs r3, #4
+ 8001892: f884 305d strb.w r3, [r4, #93] ; 0x5d
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 8001896: 6aa3 ldr r3, [r4, #40] ; 0x28
+ hspi->RxXferSize = Size;
+ 8001898: f8a4 5044 strh.w r5, [r4, #68] ; 0x44
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 800189c: 2100 movs r1, #0
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 800189e: f5b3 5f00 cmp.w r3, #8192 ; 0x2000
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ 80018a2: 6621 str r1, [r4, #96] ; 0x60
+ hspi->TxISR = NULL;
+ 80018a4: e9c4 1113 strd r1, r1, [r4, #76] ; 0x4c
+ hspi->RxXferCount = Size;
+ 80018a8: f8a4 5046 strh.w r5, [r4, #70] ; 0x46
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ 80018ac: 6426 str r6, [r4, #64] ; 0x40
+ SPI_RESET_CRC(hspi);
+ 80018ae: 6825 ldr r5, [r4, #0]
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ 80018b0: 63a1 str r1, [r4, #56] ; 0x38
+ hspi->TxXferSize = 0U;
+ 80018b2: 87a1 strh r1, [r4, #60] ; 0x3c
+ hspi->TxXferCount = 0U;
+ 80018b4: 87e1 strh r1, [r4, #62] ; 0x3e
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 80018b6: d10d bne.n 80018d4 <HAL_SPI_Receive+0xa6>
+ SPI_RESET_CRC(hspi);
+ 80018b8: 682b ldr r3, [r5, #0]
+ 80018ba: f423 5300 bic.w r3, r3, #8192 ; 0x2000
+ 80018be: 602b str r3, [r5, #0]
+ 80018c0: 682b ldr r3, [r5, #0]
+ 80018c2: f443 5300 orr.w r3, r3, #8192 ; 0x2000
+ 80018c6: 602b str r3, [r5, #0]
+ hspi->RxXferCount--;
+ 80018c8: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46
+ 80018cc: 3b01 subs r3, #1
+ 80018ce: b29b uxth r3, r3
+ 80018d0: f8a4 3046 strh.w r3, [r4, #70] ; 0x46
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 80018d4: 68e3 ldr r3, [r4, #12]
+ 80018d6: f5b3 6fe0 cmp.w r3, #1792 ; 0x700
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 80018da: 686b ldr r3, [r5, #4]
+ 80018dc: bf8c ite hi
+ 80018de: f423 5380 bichi.w r3, r3, #4096 ; 0x1000
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ 80018e2: f443 5380 orrls.w r3, r3, #4096 ; 0x1000
+ 80018e6: 606b str r3, [r5, #4]
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 80018e8: 68a3 ldr r3, [r4, #8]
+ 80018ea: f5b3 4f00 cmp.w r3, #32768 ; 0x8000
+ SPI_1LINE_RX(hspi);
+ 80018ee: bf02 ittt eq
+ 80018f0: 682b ldreq r3, [r5, #0]
+ 80018f2: f423 4380 biceq.w r3, r3, #16384 ; 0x4000
+ 80018f6: 602b streq r3, [r5, #0]
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ 80018f8: 682b ldr r3, [r5, #0]
+ 80018fa: 0658 lsls r0, r3, #25
+ 80018fc: d403 bmi.n 8001906 <HAL_SPI_Receive+0xd8>
+ __HAL_SPI_ENABLE(hspi);
+ 80018fe: 682b ldr r3, [r5, #0]
+ 8001900: f043 0340 orr.w r3, r3, #64 ; 0x40
+ 8001904: 602b str r3, [r5, #0]
+ while (hspi->RxXferCount > 0U)
+ 8001906: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+ 800190a: 6822 ldr r2, [r4, #0]
+ while (hspi->RxXferCount > 0U)
+ 800190c: b29b uxth r3, r3
+ 800190e: 2b00 cmp r3, #0
+ 8001910: d13e bne.n 8001990 <HAL_SPI_Receive+0x162>
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ 8001912: 6aa3 ldr r3, [r4, #40] ; 0x28
+ 8001914: f5b3 5f00 cmp.w r3, #8192 ; 0x2000
+ 8001918: d11c bne.n 8001954 <HAL_SPI_Receive+0x126>
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ 800191a: 6813 ldr r3, [r2, #0]
+ 800191c: f443 5380 orr.w r3, r3, #4096 ; 0x1000
+ 8001920: 6013 str r3, [r2, #0]
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 8001922: 6893 ldr r3, [r2, #8]
+ 8001924: 07df lsls r7, r3, #31
+ 8001926: d5fc bpl.n 8001922 <HAL_SPI_Receive+0xf4>
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ 8001928: 68e3 ldr r3, [r4, #12]
+ 800192a: f5b3 6fe0 cmp.w r3, #1792 ; 0x700
+ (*(uint8_t *)pData) = *(__IO uint8_t *)&hspi->Instance->DR;
+ 800192e: bf95 itete ls
+ 8001930: 7b13 ldrbls r3, [r2, #12]
+ *((uint16_t *)pData) = hspi->Instance->DR;
+ 8001932: 68d3 ldrhi r3, [r2, #12]
+ (*(uint8_t *)pData) = *(__IO uint8_t *)&hspi->Instance->DR;
+ 8001934: 7033 strbls r3, [r6, #0]
+ *((uint16_t *)pData) = hspi->Instance->DR;
+ 8001936: 8033 strhhi r3, [r6, #0]
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 8001938: 6823 ldr r3, [r4, #0]
+ 800193a: 689a ldr r2, [r3, #8]
+ 800193c: 07d6 lsls r6, r2, #31
+ 800193e: d5fc bpl.n 800193a <HAL_SPI_Receive+0x10c>
+ if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ 8001940: 68e1 ldr r1, [r4, #12]
+ 8001942: f5b1 6f70 cmp.w r1, #3840 ; 0xf00
+ 8001946: d142 bne.n 80019ce <HAL_SPI_Receive+0x1a0>
+ tmpreg = hspi->Instance->DR;
+ 8001948: 68db ldr r3, [r3, #12]
+ 800194a: b29b uxth r3, r3
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 800194c: f8ad 300e strh.w r3, [sp, #14]
+ UNUSED(tmpreg);
+ 8001950: f8bd 300e ldrh.w r3, [sp, #14]
+ * @param Tickstart: tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
+{
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 8001954: 6861 ldr r1, [r4, #4]
+ 8001956: 6823 ldr r3, [r4, #0]
+ 8001958: f5b1 7f82 cmp.w r1, #260 ; 0x104
+ 800195c: d10a bne.n 8001974 <HAL_SPI_Receive+0x146>
+ 800195e: 68a2 ldr r2, [r4, #8]
+ 8001960: f5b2 4f00 cmp.w r2, #32768 ; 0x8000
+ 8001964: d002 beq.n 800196c <HAL_SPI_Receive+0x13e>
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ 8001966: f5b2 6f80 cmp.w r2, #1024 ; 0x400
+ 800196a: d103 bne.n 8001974 <HAL_SPI_Receive+0x146>
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ 800196c: 681a ldr r2, [r3, #0]
+ 800196e: f022 0240 bic.w r2, r2, #64 ; 0x40
+ 8001972: 601a str r2, [r3, #0]
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 8001974: 689a ldr r2, [r3, #8]
+ 8001976: 0610 lsls r0, r2, #24
+ 8001978: d4fc bmi.n 8001974 <HAL_SPI_Receive+0x146>
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 800197a: f5b1 7f82 cmp.w r1, #260 ; 0x104
+ 800197e: d036 beq.n 80019ee <HAL_SPI_Receive+0x1c0>
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ 8001980: 689a ldr r2, [r3, #8]
+ 8001982: 06d2 lsls r2, r2, #27
+ 8001984: d445 bmi.n 8001a12 <HAL_SPI_Receive+0x1e4>
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ 8001986: 6e20 ldr r0, [r4, #96] ; 0x60
+ errorcode = HAL_BUSY;
+ 8001988: 3800 subs r0, #0
+ 800198a: bf18 it ne
+ 800198c: 2001 movne r0, #1
+error :
+ 800198e: e00e b.n 80019ae <HAL_SPI_Receive+0x180>
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+ 8001990: 6893 ldr r3, [r2, #8]
+ 8001992: 07d9 lsls r1, r3, #31
+ 8001994: d509 bpl.n 80019aa <HAL_SPI_Receive+0x17c>
+ (* (uint8_t *)pData) = *(__IO uint8_t *)&hspi->Instance->DR;
+ 8001996: 7b13 ldrb r3, [r2, #12]
+ 8001998: f806 3b01 strb.w r3, [r6], #1
+ hspi->RxXferCount--;
+ 800199c: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46
+ 80019a0: 3b01 subs r3, #1
+ 80019a2: b29b uxth r3, r3
+ 80019a4: f8a4 3046 strh.w r3, [r4, #70] ; 0x46
+ 80019a8: e7ad b.n 8001906 <HAL_SPI_Receive+0xd8>
+ if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))
+ 80019aa: b93f cbnz r7, 80019bc <HAL_SPI_Receive+0x18e>
+ errorcode = HAL_TIMEOUT;
+ 80019ac: 2003 movs r0, #3
+ hspi->State = HAL_SPI_STATE_READY;
+ 80019ae: 2301 movs r3, #1
+ 80019b0: f884 305d strb.w r3, [r4, #93] ; 0x5d
+ __HAL_UNLOCK(hspi);
+ 80019b4: 2300 movs r3, #0
+ 80019b6: f884 305c strb.w r3, [r4, #92] ; 0x5c
+ return errorcode;
+ 80019ba: e74f b.n 800185c <HAL_SPI_Receive+0x2e>
+ if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))
+ 80019bc: 1c7b adds r3, r7, #1
+ 80019be: d0a2 beq.n 8001906 <HAL_SPI_Receive+0xd8>
+ 80019c0: f005 fbc6 bl 8007150 <HAL_GetTick>
+ 80019c4: eba0 0008 sub.w r0, r0, r8
+ 80019c8: 42b8 cmp r0, r7
+ 80019ca: d39c bcc.n 8001906 <HAL_SPI_Receive+0xd8>
+ 80019cc: e7ee b.n 80019ac <HAL_SPI_Receive+0x17e>
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 80019ce: 7b1a ldrb r2, [r3, #12]
+ 80019d0: f8ad 200e strh.w r2, [sp, #14]
+ if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ 80019d4: f5b1 6fe0 cmp.w r1, #1792 ; 0x700
+ UNUSED(tmpreg);
+ 80019d8: f8bd 200e ldrh.w r2, [sp, #14]
+ if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ 80019dc: d1ba bne.n 8001954 <HAL_SPI_Receive+0x126>
+ 80019de: 6b22 ldr r2, [r4, #48] ; 0x30
+ 80019e0: 2a02 cmp r2, #2
+ 80019e2: d1b7 bne.n 8001954 <HAL_SPI_Receive+0x126>
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ 80019e4: 689a ldr r2, [r3, #8]
+ 80019e6: 07d5 lsls r5, r2, #31
+ 80019e8: d5fc bpl.n 80019e4 <HAL_SPI_Receive+0x1b6>
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ 80019ea: 7b1b ldrb r3, [r3, #12]
+ 80019ec: e7ae b.n 800194c <HAL_SPI_Receive+0x11e>
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ 80019ee: 68a2 ldr r2, [r4, #8]
+ 80019f0: f5b2 4f00 cmp.w r2, #32768 ; 0x8000
+ 80019f4: d002 beq.n 80019fc <HAL_SPI_Receive+0x1ce>
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ 80019f6: f5b2 6f80 cmp.w r2, #1024 ; 0x400
+ 80019fa: d1c1 bne.n 8001980 <HAL_SPI_Receive+0x152>
+ while ((hspi->Instance->SR & Fifo) != State)
+ 80019fc: 689a ldr r2, [r3, #8]
+ 80019fe: f412 6fc0 tst.w r2, #1536 ; 0x600
+ 8001a02: d0bd beq.n 8001980 <HAL_SPI_Receive+0x152>
+ tmpreg = *((__IO uint8_t *)&hspi->Instance->DR);
+ 8001a04: 7b1a ldrb r2, [r3, #12]
+ 8001a06: b2d2 uxtb r2, r2
+ 8001a08: f88d 200d strb.w r2, [sp, #13]
+ UNUSED(tmpreg);
+ 8001a0c: f89d 200d ldrb.w r2, [sp, #13]
+ 8001a10: e7f4 b.n 80019fc <HAL_SPI_Receive+0x1ce>
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ 8001a12: 6e22 ldr r2, [r4, #96] ; 0x60
+ 8001a14: f042 0202 orr.w r2, r2, #2
+ 8001a18: 6622 str r2, [r4, #96] ; 0x60
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ 8001a1a: f64f 72ef movw r2, #65519 ; 0xffef
+ 8001a1e: 609a str r2, [r3, #8]
+ 8001a20: e7b1 b.n 8001986 <HAL_SPI_Receive+0x158>
+ errorcode = HAL_BUSY;
+ 8001a22: 2002 movs r0, #2
+ 8001a24: e7c3 b.n 80019ae <HAL_SPI_Receive+0x180>
+ __HAL_LOCK(hspi);
+ 8001a26: 2002 movs r0, #2
+ 8001a28: e718 b.n 800185c <HAL_SPI_Receive+0x2e>
+ ...
+
+08001a2c <checksum_more>:
+
+// checksum_more()
+//
+ static void
+checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
+{
+ 8001a2c: b5f8 push {r3, r4, r5, r6, r7, lr}
+ 8001a2e: 460c mov r4, r1
+ // mk4 has hardware hash engine, and no DFU button
+ int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;
+ 8001a30: 6809 ldr r1, [r1, #0]
+{
+ 8001a32: 461d mov r5, r3
+ int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;
+ 8001a34: 2364 movs r3, #100 ; 0x64
+{
+ 8001a36: 4617 mov r7, r2
+ 8001a38: 4606 mov r6, r0
+ int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;
+ 8001a3a: 4359 muls r1, r3
+ puts2("Verify %0x");
+ puthex2(percent);
+ putchar('\n');
+#endif
+
+ oled_show_progress(screen_verify, percent);
+ 8001a3c: 4807 ldr r0, [pc, #28] ; (8001a5c <checksum_more+0x30>)
+ 8001a3e: 4b08 ldr r3, [pc, #32] ; (8001a60 <checksum_more+0x34>)
+ 8001a40: fbb1 f1f3 udiv r1, r1, r3
+ 8001a44: f7ff fa4e bl 8000ee4 <oled_show_progress>
+
+ sha256_update(ctx, addr, len);
+ 8001a48: 462a mov r2, r5
+ 8001a4a: 4639 mov r1, r7
+ 8001a4c: 4630 mov r0, r6
+ 8001a4e: f003 fd5d bl 800550c <sha256_update>
+ *total += len;
+ 8001a52: 6823 ldr r3, [r4, #0]
+ 8001a54: 442b add r3, r5
+ 8001a56: 6023 str r3, [r4, #0]
+}
+ 8001a58: bdf8 pop {r3, r4, r5, r6, r7, pc}
+ 8001a5a: bf00 nop
+ 8001a5c: 0800e2c8 .word 0x0800e2c8
+ 8001a60: 0018541c .word 0x0018541c
+
+08001a64 <checksum_flash>:
+
+// checksum_flash()
+//
+ void
+checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32], uint32_t fw_length)
+{
+ 8001a64: b570 push {r4, r5, r6, lr}
+ 8001a66: b09c sub sp, #112 ; 0x70
+ 8001a68: 4606 mov r6, r0
+ 8001a6a: 460d mov r5, r1
+ 8001a6c: 4614 mov r4, r2
+ const uint8_t *start = (const uint8_t *)FIRMWARE_START;
+
+ rng_delay();
+ 8001a6e: f000 fe9b bl 80027a8 <rng_delay>
+
+ SHA256_CTX ctx;
+ uint32_t total_len = 0;
+ 8001a72: 2300 movs r3, #0
+ 8001a74: 9300 str r3, [sp, #0]
+
+ if(fw_length == 0) {
+ 8001a76: 2c00 cmp r4, #0
+ 8001a78: d15f bne.n 8001b3a <checksum_flash+0xd6>
+ uint8_t first[32];
+ sha256_init(&ctx);
+ 8001a7a: a809 add r0, sp, #36 ; 0x24
+ 8001a7c: f003 fd38 bl 80054f0 <sha256_init>
+
+ // use length from header in flash
+ fw_length = FW_HDR->firmware_length;
+ 8001a80: 4b36 ldr r3, [pc, #216] ; (8001b5c <checksum_flash+0xf8>)
+
+ // start of firmware (just after we end) to header
+ checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
+ 8001a82: 4a37 ldr r2, [pc, #220] ; (8001b60 <checksum_flash+0xfc>)
+ fw_length = FW_HDR->firmware_length;
+ 8001a84: f8d3 4098 ldr.w r4, [r3, #152] ; 0x98
+ checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
+ 8001a88: 4669 mov r1, sp
+ 8001a8a: f44f 537f mov.w r3, #16320 ; 0x3fc0
+ 8001a8e: a809 add r0, sp, #36 ; 0x24
+ 8001a90: f7ff ffcc bl 8001a2c <checksum_more>
+
+ // from after header to end
+ checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE,
+ 8001a94: 4a33 ldr r2, [pc, #204] ; (8001b64 <checksum_flash+0x100>)
+ 8001a96: f5a4 4380 sub.w r3, r4, #16384 ; 0x4000
+ 8001a9a: 4669 mov r1, sp
+ 8001a9c: a809 add r0, sp, #36 ; 0x24
+ 8001a9e: f7ff ffc5 bl 8001a2c <checksum_more>
+ fw_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
+
+ sha256_final(&ctx, first);
+ 8001aa2: a901 add r1, sp, #4
+ 8001aa4: a809 add r0, sp, #36 ; 0x24
+ 8001aa6: f003 fd77 bl 8005598 <sha256_final>
+
+ // double SHA256
+ sha256_single(first, sizeof(first), fw_digest);
+ 8001aaa: 4632 mov r2, r6
+ 8001aac: 2120 movs r1, #32
+ 8001aae: a801 add r0, sp, #4
+ 8001ab0: f003 fd86 bl 80055c0 <sha256_single>
+ // fw_digest should already be populated by caller
+ total_len = fw_length - 64;
+ }
+
+ // start over, and get the rest of flash. All of it.
+ sha256_init(&ctx);
+ 8001ab4: a809 add r0, sp, #36 ; 0x24
+ 8001ab6: f003 fd1b bl 80054f0 <sha256_init>
+
+ // .. and chain in what we have so far
+ sha256_update(&ctx, fw_digest, 32);
+ 8001aba: 2220 movs r2, #32
+ 8001abc: 4631 mov r1, r6
+ 8001abe: a809 add r0, sp, #36 ; 0x24
+ 8001ac0: f003 fd24 bl 800550c <sha256_update>
+
+ // Bootloader, including pairing secret area, but excluding MCU keys.
+ const uint8_t *base = (const uint8_t *)BL_FLASH_BASE;
+ checksum_more(&ctx, &total_len, base, ((uint8_t *)MCU_KEYS)-base);
+ 8001ac4: f44f 33f0 mov.w r3, #122880 ; 0x1e000
+ 8001ac8: f04f 6200 mov.w r2, #134217728 ; 0x8000000
+ 8001acc: 4669 mov r1, sp
+ 8001ace: a809 add r0, sp, #36 ; 0x24
+ 8001ad0: f7ff ffac bl 8001a2c <checksum_more>
+
+ // Probably-blank area after firmware, and filesystem area.
+ // Important: firmware images (fw_length) must be aligned with flash erase unit size (4k).
+ const uint8_t *fs = start + fw_length;
+ const uint8_t *last = base + MAIN_FLASH_SIZE;
+ checksum_more(&ctx, &total_len, fs, last-fs);
+ 8001ad4: f104 6200 add.w r2, r4, #134217728 ; 0x8000000
+ 8001ad8: f5c4 13b0 rsb r3, r4, #1441792 ; 0x160000
+ 8001adc: f502 3200 add.w r2, r2, #131072 ; 0x20000
+ 8001ae0: 4669 mov r1, sp
+ 8001ae2: a809 add r0, sp, #36 ; 0x24
+ 8001ae4: f7ff ffa2 bl 8001a2c <checksum_more>
+
+ rng_delay();
+ 8001ae8: f000 fe5e bl 80027a8 <rng_delay>
+
+ // OTP area
+ checksum_more(&ctx, &total_len, (void *)0x1fff7000, 0x400);
+ 8001aec: 4a1e ldr r2, [pc, #120] ; (8001b68 <checksum_flash+0x104>)
+ 8001aee: f44f 6380 mov.w r3, #1024 ; 0x400
+ 8001af2: 4669 mov r1, sp
+ 8001af4: a809 add r0, sp, #36 ; 0x24
+ 8001af6: f7ff ff99 bl 8001a2c <checksum_more>
+
+ // "just in case" ... the option bytes (2 banks)
+ checksum_more(&ctx, &total_len, (void *)0x1fff7800, 0x28);
+ 8001afa: 4a1c ldr r2, [pc, #112] ; (8001b6c <checksum_flash+0x108>)
+ 8001afc: 2328 movs r3, #40 ; 0x28
+ 8001afe: 4669 mov r1, sp
+ 8001b00: a809 add r0, sp, #36 ; 0x24
+ 8001b02: f7ff ff93 bl 8001a2c <checksum_more>
+ checksum_more(&ctx, &total_len, (void *)0x1ffff800, 0x28);
+ 8001b06: 4a1a ldr r2, [pc, #104] ; (8001b70 <checksum_flash+0x10c>)
+ 8001b08: 2328 movs r3, #40 ; 0x28
+ 8001b0a: 4669 mov r1, sp
+ 8001b0c: a809 add r0, sp, #36 ; 0x24
+ 8001b0e: f7ff ff8d bl 8001a2c <checksum_more>
+
+ // System ROM (they say it can't change, but clearly
+ // implemented as flash cells)
+ checksum_more(&ctx, &total_len, (void *)0x1fff0000, 0x7000);
+ 8001b12: 4a18 ldr r2, [pc, #96] ; (8001b74 <checksum_flash+0x110>)
+ 8001b14: f44f 43e0 mov.w r3, #28672 ; 0x7000
+ 8001b18: 4669 mov r1, sp
+ 8001b1a: a809 add r0, sp, #36 ; 0x24
+ 8001b1c: f7ff ff86 bl 8001a2c <checksum_more>
+
+ // device serial number, just for kicks
+ checksum_more(&ctx, &total_len, (void *)0x1fff7590, 12);
+ 8001b20: 4a15 ldr r2, [pc, #84] ; (8001b78 <checksum_flash+0x114>)
+ 8001b22: 230c movs r3, #12
+ 8001b24: 4669 mov r1, sp
+ 8001b26: a809 add r0, sp, #36 ; 0x24
+ 8001b28: f7ff ff80 bl 8001a2c <checksum_more>
+
+ ASSERT(total_len == TOTAL_CHECKSUM_LEN);
+ 8001b2c: 4b13 ldr r3, [pc, #76] ; (8001b7c <checksum_flash+0x118>)
+ 8001b2e: 9a00 ldr r2, [sp, #0]
+ 8001b30: 429a cmp r2, r3
+ 8001b32: d006 beq.n 8001b42 <checksum_flash+0xde>
+ 8001b34: 4812 ldr r0, [pc, #72] ; (8001b80 <checksum_flash+0x11c>)
+ 8001b36: f7fe ff87 bl 8000a48 <fatal_error>
+ total_len = fw_length - 64;
+ 8001b3a: f1a4 0340 sub.w r3, r4, #64 ; 0x40
+ 8001b3e: 9300 str r3, [sp, #0]
+ 8001b40: e7b8 b.n 8001ab4 <checksum_flash+0x50>
+
+ sha256_final(&ctx, world_digest);
+ 8001b42: 4629 mov r1, r5
+ 8001b44: a809 add r0, sp, #36 ; 0x24
+ 8001b46: f003 fd27 bl 8005598 <sha256_final>
+
+ // double SHA256 (a bitcoin fetish)
+ sha256_single(world_digest, 32, world_digest);
+ 8001b4a: 462a mov r2, r5
+ 8001b4c: 2120 movs r1, #32
+ 8001b4e: 4628 mov r0, r5
+ 8001b50: f003 fd36 bl 80055c0 <sha256_single>
+
+ rng_delay();
+ 8001b54: f000 fe28 bl 80027a8 <rng_delay>
+}
+ 8001b58: b01c add sp, #112 ; 0x70
+ 8001b5a: bd70 pop {r4, r5, r6, pc}
+ 8001b5c: 08023f00 .word 0x08023f00
+ 8001b60: 08020000 .word 0x08020000
+ 8001b64: 08024000 .word 0x08024000
+ 8001b68: 1fff7000 .word 0x1fff7000
+ 8001b6c: 1fff7800 .word 0x1fff7800
+ 8001b70: 1ffff800 .word 0x1ffff800
+ 8001b74: 1fff0000 .word 0x1fff0000
+ 8001b78: 1fff7590 .word 0x1fff7590
+ 8001b7c: 0018541c .word 0x0018541c
+ 8001b80: 0800e466 .word 0x0800e466
+
+08001b84 <get_min_version>:
+// Scan the OTP area and determine what the current min-version (timestamp)
+// we can allow. All zeros if any if okay.
+//
+ void
+get_min_version(uint8_t min_version[8])
+{
+ 8001b84: b570 push {r4, r5, r6, lr}
+ 8001b86: 4604 mov r4, r0
+ const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;
+ 8001b88: 4d0c ldr r5, [pc, #48] ; (8001bbc <get_min_version+0x38>)
+
+ rng_delay();
+ memset(min_version, 0, 8);
+
+ for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
+ 8001b8a: 4e0d ldr r6, [pc, #52] ; (8001bc0 <get_min_version+0x3c>)
+ rng_delay();
+ 8001b8c: f000 fe0c bl 80027a8 <rng_delay>
+ memset(min_version, 0, 8);
+ 8001b90: 2300 movs r3, #0
+ 8001b92: 6023 str r3, [r4, #0]
+ 8001b94: 6063 str r3, [r4, #4]
+ // is it programmed?
+ if(otp[0] == 0xff) continue;
+
+ // is it a timestamp value?
+ if(otp[0] >= 0x40) continue;
+ if(otp[0] < 0x10) continue;
+ 8001b96: 782b ldrb r3, [r5, #0]
+ 8001b98: 3b10 subs r3, #16
+ 8001b9a: 2b2f cmp r3, #47 ; 0x2f
+ 8001b9c: d80a bhi.n 8001bb4 <get_min_version+0x30>
+
+ if(memcmp(otp, min_version, 8) > 0) {
+ 8001b9e: 4621 mov r1, r4
+ 8001ba0: 2208 movs r2, #8
+ 8001ba2: 4628 mov r0, r5
+ 8001ba4: f00b fd60 bl 800d668 <memcmp>
+ 8001ba8: 2800 cmp r0, #0
+ memcpy(min_version, otp, 8);
+ 8001baa: bfc1 itttt gt
+ 8001bac: 462b movgt r3, r5
+ 8001bae: cb03 ldmiagt r3!, {r0, r1}
+ 8001bb0: 6020 strgt r0, [r4, #0]
+ 8001bb2: 6061 strgt r1, [r4, #4]
+ for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
+ 8001bb4: 3508 adds r5, #8
+ 8001bb6: 42b5 cmp r5, r6
+ 8001bb8: d1ed bne.n 8001b96 <get_min_version+0x12>
+ }
+ }
+}
+ 8001bba: bd70 pop {r4, r5, r6, pc}
+ 8001bbc: 1fff7000 .word 0x1fff7000
+ 8001bc0: 1fff7400 .word 0x1fff7400
+
+08001bc4 <check_is_downgrade>:
+
+// check_is_downgrade()
+//
+ bool
+check_is_downgrade(const uint8_t timestamp[8], const char *version)
+{
+ 8001bc4: b513 push {r0, r1, r4, lr}
+ 8001bc6: 4604 mov r4, r0
+#ifndef FOR_Q1_ONLY
+ if(version) {
+ 8001bc8: b129 cbz r1, 8001bd6 <check_is_downgrade+0x12>
+ int major = (version[1] == '.') ? (version[0]-'0') : 10;
+ 8001bca: 784b ldrb r3, [r1, #1]
+ 8001bcc: 2b2e cmp r3, #46 ; 0x2e
+ 8001bce: d102 bne.n 8001bd6 <check_is_downgrade+0x12>
+ if(major < 3) {
+ 8001bd0: 780b ldrb r3, [r1, #0]
+ 8001bd2: 2b32 cmp r3, #50 ; 0x32
+ 8001bd4: d90a bls.n 8001bec <check_is_downgrade+0x28>
+ }
+#endif
+
+ // look at FW_HDR->timestamp and compare to a growing list in main flash OTP
+ uint8_t min[8];
+ get_min_version(min);
+ 8001bd6: 4668 mov r0, sp
+ 8001bd8: f7ff ffd4 bl 8001b84 <get_min_version>
+
+ return (memcmp(timestamp, min, 8) < 0);
+ 8001bdc: 2208 movs r2, #8
+ 8001bde: 4669 mov r1, sp
+ 8001be0: 4620 mov r0, r4
+ 8001be2: f00b fd41 bl 800d668 <memcmp>
+ 8001be6: 0fc0 lsrs r0, r0, #31
+}
+ 8001be8: b002 add sp, #8
+ 8001bea: bd10 pop {r4, pc}
+ return true;
+ 8001bec: 2001 movs r0, #1
+ 8001bee: e7fb b.n 8001be8 <check_is_downgrade+0x24>
+
+08001bf0 <warn_fishy_firmware>:
+
+// warn_fishy_firmware()
+//
+ void
+warn_fishy_firmware(const uint8_t *pixels)
+{
+ 8001bf0: b538 push {r3, r4, r5, lr}
+ 8001bf2: 4605 mov r5, r0
+ const int wait = 100;
+#else
+ const int wait = 10;
+#endif
+
+ for(int i=0; i < wait; i++) {
+ 8001bf4: 2400 movs r4, #0
+ oled_show_progress(pixels, (i*100)/wait);
+ 8001bf6: 4621 mov r1, r4
+ 8001bf8: 4628 mov r0, r5
+ 8001bfa: f7ff f973 bl 8000ee4 <oled_show_progress>
+ for(int i=0; i < wait; i++) {
+ 8001bfe: 3401 adds r4, #1
+
+ delay_ms(250);
+ 8001c00: 20fa movs r0, #250 ; 0xfa
+ 8001c02: f001 fe8f bl 8003924 <delay_ms>
+ for(int i=0; i < wait; i++) {
+ 8001c06: 2c64 cmp r4, #100 ; 0x64
+ 8001c08: d1f5 bne.n 8001bf6 <warn_fishy_firmware+0x6>
+ }
+}
+ 8001c0a: bd38 pop {r3, r4, r5, pc}
+
+08001c0c <verify_header>:
+
+// verify_header()
+//
+ bool
+verify_header(const coldcardFirmwareHeader_t *hdr)
+{
+ 8001c0c: b510 push {r4, lr}
+ 8001c0e: 4604 mov r4, r0
+ rng_delay();
+ 8001c10: f000 fdca bl 80027a8 <rng_delay>
+
+ if(hdr->magic_value != FW_HEADER_MAGIC) goto fail;
+ 8001c14: 6822 ldr r2, [r4, #0]
+ 8001c16: 4b0b ldr r3, [pc, #44] ; (8001c44 <verify_header+0x38>)
+ 8001c18: 429a cmp r2, r3
+ 8001c1a: d110 bne.n 8001c3e <verify_header+0x32>
+ if(hdr->version_string[0] == 0x0) goto fail;
+ 8001c1c: 7b20 ldrb r0, [r4, #12]
+ 8001c1e: b168 cbz r0, 8001c3c <verify_header+0x30>
+ if(hdr->timestamp[0] >= 0x40) goto fail; // 22 yr product lifetime
+ 8001c20: 7923 ldrb r3, [r4, #4]
+ 8001c22: 2b3f cmp r3, #63 ; 0x3f
+ 8001c24: d80b bhi.n 8001c3e <verify_header+0x32>
+ if(hdr->firmware_length < FW_MIN_LENGTH) goto fail;
+ 8001c26: 69a3 ldr r3, [r4, #24]
+ 8001c28: f5a3 2380 sub.w r3, r3, #262144 ; 0x40000
+ 8001c2c: f5b3 1fd0 cmp.w r3, #1703936 ; 0x1a0000
+ 8001c30: d205 bcs.n 8001c3e <verify_header+0x32>
+ if(hdr->firmware_length >= FW_MAX_LENGTH_MK4) goto fail;
+ if(hdr->pubkey_num >= NUM_KNOWN_PUBKEYS) goto fail;
+ 8001c32: 6960 ldr r0, [r4, #20]
+ 8001c34: 2805 cmp r0, #5
+ 8001c36: bf8c ite hi
+ 8001c38: 2000 movhi r0, #0
+ 8001c3a: 2001 movls r0, #1
+
+ return true;
+fail:
+ return false;
+}
+ 8001c3c: bd10 pop {r4, pc}
+ return false;
+ 8001c3e: 2000 movs r0, #0
+ 8001c40: e7fc b.n 8001c3c <verify_header+0x30>
+ 8001c42: bf00 nop
+ 8001c44: cc001234 .word 0xcc001234
+
+08001c48 <verify_signature>:
+//
+// Given double-sha256 over the firmware bytes, check the signature.
+//
+ bool
+verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_check[32])
+{
+ 8001c48: b530 push {r4, r5, lr}
+ // this takes a few ms at least, not fast.
+ int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32,
+ 8001c4a: 6943 ldr r3, [r0, #20]
+ 8001c4c: 4d0b ldr r5, [pc, #44] ; (8001c7c <verify_signature+0x34>)
+{
+ 8001c4e: b085 sub sp, #20
+ int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32,
+ 8001c50: eb05 1583 add.w r5, r5, r3, lsl #6
+{
+ 8001c54: 4604 mov r4, r0
+ 8001c56: 9103 str r1, [sp, #12]
+ int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32,
+ 8001c58: f004 fe76 bl 8006948 <uECC_secp256k1>
+ 8001c5c: f104 0340 add.w r3, r4, #64 ; 0x40
+ 8001c60: 9903 ldr r1, [sp, #12]
+ 8001c62: 9000 str r0, [sp, #0]
+ 8001c64: 2220 movs r2, #32
+ 8001c66: 4628 mov r0, r5
+ 8001c68: f005 f8f5 bl 8006e56 <uECC_verify>
+ 8001c6c: 4604 mov r4, r0
+ hdr->signature, uECC_secp256k1());
+
+ //puts(ok ? "Sig ok" : "Sig fail");
+ rng_delay();
+ 8001c6e: f000 fd9b bl 80027a8 <rng_delay>
+
+ return ok;
+}
+ 8001c72: 1e20 subs r0, r4, #0
+ 8001c74: bf18 it ne
+ 8001c76: 2001 movne r0, #1
+ 8001c78: b005 add sp, #20
+ 8001c7a: bd30 pop {r4, r5, pc}
+ 8001c7c: 0800e4e0 .word 0x0800e4e0
+
+08001c80 <verify_firmware_in_ram>:
+// Check hdr, and even signature of protential new firmware in PSRAM.
+// Returns checksum needed for 608
+//
+ bool
+verify_firmware_in_ram(const uint8_t *start, uint32_t len, uint8_t world_check[32])
+{
+ 8001c80: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr}
+ const coldcardFirmwareHeader_t *hdr = (const coldcardFirmwareHeader_t *)
+ 8001c84: f500 567e add.w r6, r0, #16256 ; 0x3f80
+{
+ 8001c88: b09c sub sp, #112 ; 0x70
+ 8001c8a: 4605 mov r5, r0
+ (start + FW_HEADER_OFFSET);
+ uint8_t fw_digest[32];
+
+ // check basics like verison, hw compat, etc
+ if(!verify_header(hdr)) goto fail;
+ 8001c8c: 4630 mov r0, r6
+{
+ 8001c8e: 4617 mov r7, r2
+ if(!verify_header(hdr)) goto fail;
+ 8001c90: f7ff ffbc bl 8001c0c <verify_header>
+ 8001c94: 4604 mov r4, r0
+ 8001c96: b150 cbz r0, 8001cae <verify_firmware_in_ram+0x2e>
+
+ if(check_is_downgrade(hdr->timestamp, (const char *)hdr->version_string)) {
+ 8001c98: f106 010c add.w r1, r6, #12
+ 8001c9c: 1d30 adds r0, r6, #4
+ 8001c9e: f7ff ff91 bl 8001bc4 <check_is_downgrade>
+ 8001ca2: 4604 mov r4, r0
+ 8001ca4: b138 cbz r0, 8001cb6 <verify_firmware_in_ram+0x36>
+ puts("downgrade");
+ 8001ca6: 481e ldr r0, [pc, #120] ; (8001d20 <verify_firmware_in_ram+0xa0>)
+ 8001ca8: f003 f8b2 bl 8004e10 <puts>
+
+ checksum_flash(fw_digest, world_check, hdr->firmware_length);
+
+ return true;
+fail:
+ return false;
+ 8001cac: 2400 movs r4, #0
+}
+ 8001cae: 4620 mov r0, r4
+ 8001cb0: b01c add sp, #112 ; 0x70
+ 8001cb2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc}
+ rng_delay();
+ 8001cb6: f000 fd77 bl 80027a8 <rng_delay>
+ hdr->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
+ 8001cba: f505 5840 add.w r8, r5, #12288 ; 0x3000
+ sha256_init(&ctx);
+ 8001cbe: a809 add r0, sp, #36 ; 0x24
+ uint32_t total_len = 0;
+ 8001cc0: 9400 str r4, [sp, #0]
+ sha256_init(&ctx);
+ 8001cc2: f003 fc15 bl 80054f0 <sha256_init>
+ checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
+ 8001cc6: f44f 537f mov.w r3, #16320 ; 0x3fc0
+ 8001cca: 462a mov r2, r5
+ 8001ccc: 4669 mov r1, sp
+ 8001cce: a809 add r0, sp, #36 ; 0x24
+ 8001cd0: f7ff feac bl 8001a2c <checksum_more>
+ hdr->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
+ 8001cd4: f8d8 3f98 ldr.w r3, [r8, #3992] ; 0xf98
+ checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE,
+ 8001cd8: f505 4280 add.w r2, r5, #16384 ; 0x4000
+ 8001cdc: f5a3 4380 sub.w r3, r3, #16384 ; 0x4000
+ 8001ce0: 4669 mov r1, sp
+ 8001ce2: a809 add r0, sp, #36 ; 0x24
+ 8001ce4: f7ff fea2 bl 8001a2c <checksum_more>
+ sha256_final(&ctx, fw_digest);
+ 8001ce8: a901 add r1, sp, #4
+ 8001cea: a809 add r0, sp, #36 ; 0x24
+ 8001cec: f003 fc54 bl 8005598 <sha256_final>
+ sha256_single(fw_digest, 32, fw_digest);
+ 8001cf0: aa01 add r2, sp, #4
+ 8001cf2: 4610 mov r0, r2
+ 8001cf4: 2120 movs r1, #32
+ 8001cf6: f003 fc63 bl 80055c0 <sha256_single>
+ rng_delay();
+ 8001cfa: f000 fd55 bl 80027a8 <rng_delay>
+ if(!verify_signature(hdr, fw_digest)) {
+ 8001cfe: a901 add r1, sp, #4
+ 8001d00: 4630 mov r0, r6
+ 8001d02: f7ff ffa1 bl 8001c48 <verify_signature>
+ 8001d06: 4604 mov r4, r0
+ 8001d08: b918 cbnz r0, 8001d12 <verify_firmware_in_ram+0x92>
+ puts("sig fail");
+ 8001d0a: 4806 ldr r0, [pc, #24] ; (8001d24 <verify_firmware_in_ram+0xa4>)
+ 8001d0c: f003 f880 bl 8004e10 <puts>
+ goto fail;
+ 8001d10: e7cd b.n 8001cae <verify_firmware_in_ram+0x2e>
+ checksum_flash(fw_digest, world_check, hdr->firmware_length);
+ 8001d12: f8d8 2f98 ldr.w r2, [r8, #3992] ; 0xf98
+ 8001d16: 4639 mov r1, r7
+ 8001d18: a801 add r0, sp, #4
+ 8001d1a: f7ff fea3 bl 8001a64 <checksum_flash>
+ return true;
+ 8001d1e: e7c6 b.n 8001cae <verify_firmware_in_ram+0x2e>
+ 8001d20: 0800e46d .word 0x0800e46d
+ 8001d24: 0800e477 .word 0x0800e477
+
+08001d28 <verify_world_checksum>:
+// - don't set the light at this point.
+// - requires bootloader to have been unchanged since world_check recorded (debug issue)
+//
+ bool
+verify_world_checksum(const uint8_t world_check[32])
+{
+ 8001d28: b507 push {r0, r1, r2, lr}
+ 8001d2a: 9001 str r0, [sp, #4]
+ ae_setup();
+ 8001d2c: f000 fe60 bl 80029f0 <ae_setup>
+ ae_pair_unlock();
+ 8001d30: f001 f854 bl 8002ddc <ae_pair_unlock>
+
+ return (ae_checkmac_hard(KEYNUM_firmware, world_check) == 0);
+ 8001d34: 9901 ldr r1, [sp, #4]
+ 8001d36: 200e movs r0, #14
+ 8001d38: f001 f9de bl 80030f8 <ae_checkmac_hard>
+}
+ 8001d3c: fab0 f080 clz r0, r0
+ 8001d40: 0940 lsrs r0, r0, #5
+ 8001d42: b003 add sp, #12
+ 8001d44: f85d fb04 ldr.w pc, [sp], #4
+
+08001d48 <verify_firmware>:
+
+// verify_firmware()
+//
+ bool
+verify_firmware(void)
+{
+ 8001d48: b570 push {r4, r5, r6, lr}
+ STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE);
+
+ rng_delay();
+
+ // watch for unprogrammed header. and some
+ if(FW_HDR->version_string[0] == 0xff) goto blank;
+ 8001d4a: 4e2a ldr r6, [pc, #168] ; (8001df4 <verify_firmware+0xac>)
+{
+ 8001d4c: b090 sub sp, #64 ; 0x40
+ rng_delay();
+ 8001d4e: f000 fd2b bl 80027a8 <rng_delay>
+ if(FW_HDR->version_string[0] == 0xff) goto blank;
+ 8001d52: f896 308c ldrb.w r3, [r6, #140] ; 0x8c
+ 8001d56: 2bff cmp r3, #255 ; 0xff
+ 8001d58: d107 bne.n 8001d6a <verify_firmware+0x22>
+ puts("corrupt firmware");
+ oled_show(screen_corrupt);
+ return false;
+
+blank:
+ puts("no firmware");
+ 8001d5a: 4827 ldr r0, [pc, #156] ; (8001df8 <verify_firmware+0xb0>)
+ puts("corrupt firmware");
+ 8001d5c: f003 f858 bl 8004e10 <puts>
+ oled_show(screen_corrupt);
+ 8001d60: 4826 ldr r0, [pc, #152] ; (8001dfc <verify_firmware+0xb4>)
+ 8001d62: f7ff f87d bl 8000e60 <oled_show>
+ return false;
+ 8001d66: 2400 movs r4, #0
+ 8001d68: e030 b.n 8001dcc <verify_firmware+0x84>
+ if(!verify_header(FW_HDR)) goto fail;
+ 8001d6a: 4825 ldr r0, [pc, #148] ; (8001e00 <verify_firmware+0xb8>)
+ 8001d6c: f7ff ff4e bl 8001c0c <verify_header>
+ 8001d70: 2800 cmp r0, #0
+ 8001d72: d03c beq.n 8001dee <verify_firmware+0xa6>
+ rng_delay();
+ 8001d74: f000 fd18 bl 80027a8 <rng_delay>
+ checksum_flash(fw_check, world_check, 0);
+ 8001d78: 2200 movs r2, #0
+ 8001d7a: a908 add r1, sp, #32
+ 8001d7c: 4668 mov r0, sp
+ 8001d7e: f7ff fe71 bl 8001a64 <checksum_flash>
+ rng_delay();
+ 8001d82: f000 fd11 bl 80027a8 <rng_delay>
+ if(!verify_signature(FW_HDR, fw_check)) goto fail;
+ 8001d86: 481e ldr r0, [pc, #120] ; (8001e00 <verify_firmware+0xb8>)
+ 8001d88: 4669 mov r1, sp
+ 8001d8a: f7ff ff5d bl 8001c48 <verify_signature>
+ 8001d8e: 4604 mov r4, r0
+ 8001d90: b368 cbz r0, 8001dee <verify_firmware+0xa6>
+ int not_green = ae_set_gpio_secure(world_check);
+ 8001d92: a808 add r0, sp, #32
+ 8001d94: f001 fbc4 bl 8003520 <ae_set_gpio_secure>
+ 8001d98: 4605 mov r5, r0
+ rng_delay();
+ 8001d9a: f000 fd05 bl 80027a8 <rng_delay>
+ rng_delay();
+ 8001d9e: f000 fd03 bl 80027a8 <rng_delay>
+ return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
+ 8001da2: 4b18 ldr r3, [pc, #96] ; (8001e04 <verify_firmware+0xbc>)
+ 8001da4: 6a1b ldr r3, [r3, #32]
+ 8001da6: b2db uxtb r3, r3
+ if(!flash_is_security_level2() && not_green) {
+ 8001da8: 2bcc cmp r3, #204 ; 0xcc
+ 8001daa: d008 beq.n 8001dbe <verify_firmware+0x76>
+ 8001dac: b18d cbz r5, 8001dd2 <verify_firmware+0x8a>
+ oled_show_progress(screen_verify, 100);
+ 8001dae: 4816 ldr r0, [pc, #88] ; (8001e08 <verify_firmware+0xc0>)
+ 8001db0: 2164 movs r1, #100 ; 0x64
+ 8001db2: f7ff f897 bl 8000ee4 <oled_show_progress>
+ puts("Factory boot");
+ 8001db6: 4815 ldr r0, [pc, #84] ; (8001e0c <verify_firmware+0xc4>)
+ puts("Good firmware");
+ 8001db8: f003 f82a bl 8004e10 <puts>
+ 8001dbc: e006 b.n 8001dcc <verify_firmware+0x84>
+ } else if(not_green) {
+ 8001dbe: b145 cbz r5, 8001dd2 <verify_firmware+0x8a>
+ puts("WARN: Red light");
+ 8001dc0: 4813 ldr r0, [pc, #76] ; (8001e10 <verify_firmware+0xc8>)
+ 8001dc2: f003 f825 bl 8004e10 <puts>
+ warn_fishy_firmware(screen_red_light);
+ 8001dc6: 4813 ldr r0, [pc, #76] ; (8001e14 <verify_firmware+0xcc>)
+ warn_fishy_firmware(screen_devmode);
+ 8001dc8: f7ff ff12 bl 8001bf0 <warn_fishy_firmware>
+ oled_show(screen_corrupt);
+
+ return false;
+}
+ 8001dcc: 4620 mov r0, r4
+ 8001dce: b010 add sp, #64 ; 0x40
+ 8001dd0: bd70 pop {r4, r5, r6, pc}
+ } else if(FW_HDR->pubkey_num == 0) {
+ 8001dd2: f8d6 3094 ldr.w r3, [r6, #148] ; 0x94
+ 8001dd6: b923 cbnz r3, 8001de2 <verify_firmware+0x9a>
+ puts("WARN: Unsigned firmware");
+ 8001dd8: 480f ldr r0, [pc, #60] ; (8001e18 <verify_firmware+0xd0>)
+ 8001dda: f003 f819 bl 8004e10 <puts>
+ warn_fishy_firmware(screen_devmode);
+ 8001dde: 480f ldr r0, [pc, #60] ; (8001e1c <verify_firmware+0xd4>)
+ 8001de0: e7f2 b.n 8001dc8 <verify_firmware+0x80>
+ oled_show_progress(screen_verify, 100);
+ 8001de2: 4809 ldr r0, [pc, #36] ; (8001e08 <verify_firmware+0xc0>)
+ 8001de4: 2164 movs r1, #100 ; 0x64
+ 8001de6: f7ff f87d bl 8000ee4 <oled_show_progress>
+ puts("Good firmware");
+ 8001dea: 480d ldr r0, [pc, #52] ; (8001e20 <verify_firmware+0xd8>)
+ 8001dec: e7e4 b.n 8001db8 <verify_firmware+0x70>
+ puts("corrupt firmware");
+ 8001dee: 480d ldr r0, [pc, #52] ; (8001e24 <verify_firmware+0xdc>)
+ 8001df0: e7b4 b.n 8001d5c <verify_firmware+0x14>
+ 8001df2: bf00 nop
+ 8001df4: 08023f00 .word 0x08023f00
+ 8001df8: 0800e480 .word 0x0800e480
+ 8001dfc: 0800d8fb .word 0x0800d8fb
+ 8001e00: 08023f80 .word 0x08023f80
+ 8001e04: 40022000 .word 0x40022000
+ 8001e08: 0800e2c8 .word 0x0800e2c8
+ 8001e0c: 0800e48c .word 0x0800e48c
+ 8001e10: 0800e499 .word 0x0800e499
+ 8001e14: 0800ddf8 .word 0x0800ddf8
+ 8001e18: 0800e4a9 .word 0x0800e4a9
+ 8001e1c: 0800d9b8 .word 0x0800d9b8
+ 8001e20: 0800e4c1 .word 0x0800e4c1
+ 8001e24: 0800e4cf .word 0x0800e4cf
+
+08001e28 <systick_setup>:
+ void
+systick_setup(void)
+{
+ const uint32_t ticks = HCLK_FREQUENCY/1000;
+
+ SysTick->LOAD = (ticks - 1);
+ 8001e28: f04f 23e0 mov.w r3, #3758153728 ; 0xe000e000
+ 8001e2c: 4a03 ldr r2, [pc, #12] ; (8001e3c <systick_setup+0x14>)
+ 8001e2e: 615a str r2, [r3, #20]
+ SysTick->VAL = 0;
+ 8001e30: 2200 movs r2, #0
+ 8001e32: 619a str r2, [r3, #24]
+ SysTick->CTRL = SYSTICK_CLKSOURCE_HCLK | SysTick_CTRL_ENABLE_Msk;
+ 8001e34: 2205 movs r2, #5
+ 8001e36: 611a str r2, [r3, #16]
+}
+ 8001e38: 4770 bx lr
+ 8001e3a: bf00 nop
+ 8001e3c: 0001d4bf .word 0x0001d4bf
+
+08001e40 <system_init0>:
+ SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
+#endif
+
+ /* FPU settings ------------------------------------------------------------*/
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
+ 8001e40: 4a0e ldr r2, [pc, #56] ; (8001e7c <system_init0+0x3c>)
+ 8001e42: f8d2 3088 ldr.w r3, [r2, #136] ; 0x88
+ 8001e46: f443 0370 orr.w r3, r3, #15728640 ; 0xf00000
+ 8001e4a: f8c2 3088 str.w r3, [r2, #136] ; 0x88
+#endif
+
+ /* Reset the RCC clock configuration to the default reset state ------------*/
+ /* Set MSION bit */
+ RCC->CR |= RCC_CR_MSION;
+ 8001e4e: 4b0c ldr r3, [pc, #48] ; (8001e80 <system_init0+0x40>)
+ 8001e50: 681a ldr r2, [r3, #0]
+
+ /* Reset CFGR register */
+ RCC->CFGR = 0x00000000U;
+ 8001e52: 2100 movs r1, #0
+ RCC->CR |= RCC_CR_MSION;
+ 8001e54: f042 0201 orr.w r2, r2, #1
+ 8001e58: 601a str r2, [r3, #0]
+ RCC->CFGR = 0x00000000U;
+ 8001e5a: 6099 str r1, [r3, #8]
+
+ /* Reset HSEON, CSSON , HSION, and PLLON bits */
+ RCC->CR &= 0xEAF6FFFFU;
+ 8001e5c: 681a ldr r2, [r3, #0]
+ 8001e5e: f022 52a8 bic.w r2, r2, #352321536 ; 0x15000000
+ 8001e62: f422 2210 bic.w r2, r2, #589824 ; 0x90000
+ 8001e66: 601a str r2, [r3, #0]
+
+ /* Reset PLLCFGR register */
+ RCC->PLLCFGR = 0x00001000U;
+ 8001e68: f44f 5280 mov.w r2, #4096 ; 0x1000
+ 8001e6c: 60da str r2, [r3, #12]
+
+ /* Reset HSEBYP bit */
+ RCC->CR &= 0xFFFBFFFFU;
+ 8001e6e: 681a ldr r2, [r3, #0]
+ 8001e70: f422 2280 bic.w r2, r2, #262144 ; 0x40000
+ 8001e74: 601a str r2, [r3, #0]
+
+ /* Disable all interrupts */
+ RCC->CIER = 0x00000000U;
+ 8001e76: 6199 str r1, [r3, #24]
+}
+ 8001e78: 4770 bx lr
+ 8001e7a: bf00 nop
+ 8001e7c: e000ed00 .word 0xe000ed00
+ 8001e80: 40021000 .word 0x40021000
+
+08001e84 <clocks_setup>:
+
+// clocks_setup()
+//
+ void
+clocks_setup(void)
+{
+ 8001e84: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr}
+
+ // setup power supplies
+ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
+
+ // Configure LSE Drive Capability
+ __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
+ 8001e88: 4c41 ldr r4, [pc, #260] ; (8001f90 <clocks_setup+0x10c>)
+{
+ 8001e8a: b0c1 sub sp, #260 ; 0x104
+ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
+ 8001e8c: 2000 movs r0, #0
+ 8001e8e: f005 f975 bl 800717c <HAL_PWREx_ControlVoltageScaling>
+ __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
+ 8001e92: f8d4 3090 ldr.w r3, [r4, #144] ; 0x90
+ 8001e96: f023 0318 bic.w r3, r3, #24
+ 8001e9a: f8c4 3090 str.w r3, [r4, #144] ; 0x90
+
+ // Enable HSE Oscillator and activate PLL with HSE as source
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ 8001e9e: 2201 movs r2, #1
+ 8001ea0: f44f 3380 mov.w r3, #65536 ; 0x10000
+ 8001ea4: e9cd 230a strd r2, r3, [sp, #40] ; 0x28
+ RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
+ RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
+
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ 8001ea8: 2703 movs r7, #3
+
+ // Select PLL as system clock source and configure
+ // the HCLK, PCLK1 and PCLK2 clocks dividers
+ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
+ 8001eaa: 230f movs r3, #15
+ RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
+ 8001eac: 2500 movs r5, #0
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ 8001eae: 2602 movs r6, #2
+ | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ 8001eb0: e9cd 3705 strd r3, r7, [sp, #20]
+
+ RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
+ RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN;
+ RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP;
+ 8001eb4: f04f 0807 mov.w r8, #7
+ 8001eb8: 233c movs r3, #60 ; 0x3c
+ RCC_OscInitStruct.PLL.PLLQ = CKCC_CLK_PLLQ;
+ 8001eba: f04f 0905 mov.w r9, #5
+
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+ 8001ebe: a80a add r0, sp, #40 ; 0x28
+ RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP;
+ 8001ec0: e9cd 3817 strd r3, r8, [sp, #92] ; 0x5c
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ 8001ec4: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50
+ RCC_OscInitStruct.PLL.PLLR = CKCC_CLK_PLLR;
+ 8001ec8: e9cd 9619 strd r9, r6, [sp, #100] ; 0x64
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ 8001ecc: e9cd 5507 strd r5, r5, [sp, #28]
+ RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
+ 8001ed0: 950c str r5, [sp, #48] ; 0x30
+ RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
+ 8001ed2: 9510 str r5, [sp, #64] ; 0x40
+ RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
+ 8001ed4: 9616 str r6, [sp, #88] ; 0x58
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ 8001ed6: 9509 str r5, [sp, #36] ; 0x24
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+ 8001ed8: f006 fcf8 bl 80088cc <HAL_RCC_OscConfig>
+
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
+ 8001edc: 4649 mov r1, r9
+ 8001ede: a805 add r0, sp, #20
+ 8001ee0: f006 ffa2 bl 8008e28 <HAL_RCC_ClockConfig>
+
+ // DIS-able MSI-Hardware auto calibration mode with LSE
+ CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN);
+ 8001ee4: 6823 ldr r3, [r4, #0]
+ 8001ee6: f023 0304 bic.w r3, r3, #4
+ 8001eea: 6023 str r3, [r4, #0]
+
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C2
+ 8001eec: 4b29 ldr r3, [pc, #164] ; (8001f94 <clocks_setup+0x110>)
+ 8001eee: 931b str r3, [sp, #108] ; 0x6c
+
+ // PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is
+ // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz.
+ //
+ PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
+ PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
+ 8001ef0: f04f 5380 mov.w r3, #268435456 ; 0x10000000
+ 8001ef4: 933b str r3, [sp, #236] ; 0xec
+ PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
+ 8001ef6: f04f 6380 mov.w r3, #67108864 ; 0x4000000
+ 8001efa: 9338 str r3, [sp, #224] ; 0xe0
+ PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32; // but unused
+ PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;
+ 8001efc: 933a str r3, [sp, #232] ; 0xe8
+
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
+ 8001efe: 2318 movs r3, #24
+ PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32; // but unused
+ 8001f00: f44f 7240 mov.w r2, #768 ; 0x300
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
+ 8001f04: e9cd 381e strd r3, r8, [sp, #120] ; 0x78
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
+ |RCC_PLLSAI1_48M2CLK
+ |RCC_PLLSAI1_ADC1CLK;
+
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+ 8001f08: a81b add r0, sp, #108 ; 0x6c
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
+ 8001f0a: 4b23 ldr r3, [pc, #140] ; (8001f98 <clocks_setup+0x114>)
+ PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32; // but unused
+ 8001f0c: 923f str r2, [sp, #252] ; 0xfc
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
+ 8001f0e: 9322 str r3, [sp, #136] ; 0x88
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
+ 8001f10: e9cd 761c strd r7, r6, [sp, #112] ; 0x70
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
+ 8001f14: e9cd 6620 strd r6, r6, [sp, #128] ; 0x80
+ PeriphClkInitStruct.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1;
+ 8001f18: 9531 str r5, [sp, #196] ; 0xc4
+ PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
+ 8001f1a: 9536 str r5, [sp, #216] ; 0xd8
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+ 8001f1c: f007 faa8 bl 8009470 <HAL_RCCEx_PeriphCLKConfig>
+
+ __HAL_RCC_RTC_ENABLE();
+ 8001f20: f8d4 3090 ldr.w r3, [r4, #144] ; 0x90
+ 8001f24: f443 4300 orr.w r3, r3, #32768 ; 0x8000
+ 8001f28: f8c4 3090 str.w r3, [r4, #144] ; 0x90
+ __HAL_RCC_HASH_CLK_ENABLE(); // for SHA256
+ 8001f2c: 6ce3 ldr r3, [r4, #76] ; 0x4c
+ 8001f2e: f443 3300 orr.w r3, r3, #131072 ; 0x20000
+ 8001f32: 64e3 str r3, [r4, #76] ; 0x4c
+ 8001f34: 6ce3 ldr r3, [r4, #76] ; 0x4c
+ 8001f36: f403 3300 and.w r3, r3, #131072 ; 0x20000
+ 8001f3a: 9301 str r3, [sp, #4]
+ 8001f3c: 9b01 ldr r3, [sp, #4]
+ __HAL_RCC_SPI1_CLK_ENABLE(); // for OLED
+ 8001f3e: 6e23 ldr r3, [r4, #96] ; 0x60
+ 8001f40: f443 5380 orr.w r3, r3, #4096 ; 0x1000
+ 8001f44: 6623 str r3, [r4, #96] ; 0x60
+ 8001f46: 6e23 ldr r3, [r4, #96] ; 0x60
+ 8001f48: f403 5380 and.w r3, r3, #4096 ; 0x1000
+ 8001f4c: 9302 str r3, [sp, #8]
+ 8001f4e: 9b02 ldr r3, [sp, #8]
+ //__HAL_RCC_SPI2_CLK_ENABLE(); // for SPI flash
+ __HAL_RCC_DMAMUX1_CLK_ENABLE(); // (need this) because code missing in mpy?
+ 8001f50: 6ca3 ldr r3, [r4, #72] ; 0x48
+ 8001f52: f043 0304 orr.w r3, r3, #4
+ 8001f56: 64a3 str r3, [r4, #72] ; 0x48
+ 8001f58: 6ca3 ldr r3, [r4, #72] ; 0x48
+ 8001f5a: f003 0304 and.w r3, r3, #4
+ 8001f5e: 9303 str r3, [sp, #12]
+ 8001f60: 9b03 ldr r3, [sp, #12]
+
+ // for SE2
+ __HAL_RCC_I2C2_CLK_ENABLE();
+ 8001f62: 6da3 ldr r3, [r4, #88] ; 0x58
+ 8001f64: f443 0380 orr.w r3, r3, #4194304 ; 0x400000
+ 8001f68: 65a3 str r3, [r4, #88] ; 0x58
+ 8001f6a: 6da3 ldr r3, [r4, #88] ; 0x58
+ 8001f6c: f403 0380 and.w r3, r3, #4194304 ; 0x400000
+ 8001f70: 9304 str r3, [sp, #16]
+ 8001f72: 9b04 ldr r3, [sp, #16]
+ __HAL_RCC_I2C2_FORCE_RESET();
+ 8001f74: 6ba3 ldr r3, [r4, #56] ; 0x38
+ 8001f76: f443 0380 orr.w r3, r3, #4194304 ; 0x400000
+ 8001f7a: 63a3 str r3, [r4, #56] ; 0x38
+ __HAL_RCC_I2C2_RELEASE_RESET();
+ 8001f7c: 6ba3 ldr r3, [r4, #56] ; 0x38
+ 8001f7e: f423 0380 bic.w r3, r3, #4194304 ; 0x400000
+ 8001f82: 63a3 str r3, [r4, #56] ; 0x38
+
+ // setup SYSTICK, but we don't have the irq hooked up and not using HAL
+ // but we use it in polling mode for delay_ms()
+ systick_setup();
+ 8001f84: f7ff ff50 bl 8001e28 <systick_setup>
+
+}
+ 8001f88: b041 add sp, #260 ; 0x104
+ 8001f8a: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc}
+ 8001f8e: bf00 nop
+ 8001f90: 40021000 .word 0x40021000
+ 8001f94: 00066880 .word 0x00066880
+ 8001f98: 01110000 .word 0x01110000
+
+08001f9c <flash_ob_lock.part.0>:
+ } else {
+
+ // write changes to OB flash bytes
+
+ // Set OPTSTRT bit
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+ 8001f9c: 4b13 ldr r3, [pc, #76] ; (8001fec <flash_ob_lock.part.0+0x50>)
+ 8001f9e: 695a ldr r2, [r3, #20]
+ 8001fa0: f442 3200 orr.w r2, r2, #131072 ; 0x20000
+ 8001fa4: 615a str r2, [r3, #20]
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
+ 8001fa6: 691a ldr r2, [r3, #16]
+ 8001fa8: 03d2 lsls r2, r2, #15
+ 8001faa: d4fc bmi.n 8001fa6 <flash_ob_lock.part.0+0xa>
+ uint32_t error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
+ 8001fac: 6919 ldr r1, [r3, #16]
+ if(error) {
+ 8001fae: 4a10 ldr r2, [pc, #64] ; (8001ff0 <flash_ob_lock.part.0+0x54>)
+ 8001fb0: 4211 tst r1, r2
+ 8001fb2: d104 bne.n 8001fbe <flash_ob_lock.part.0+0x22>
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
+ 8001fb4: 691a ldr r2, [r3, #16]
+ 8001fb6: 07d0 lsls r0, r2, #31
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ 8001fb8: bf44 itt mi
+ 8001fba: 2201 movmi r2, #1
+ 8001fbc: 611a strmi r2, [r3, #16]
+
+ /// Wait for update to complete
+ _flash_wait_done();
+
+ // lock OB again.
+ SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
+ 8001fbe: 4b0b ldr r3, [pc, #44] ; (8001fec <flash_ob_lock.part.0+0x50>)
+ 8001fc0: 695a ldr r2, [r3, #20]
+ 8001fc2: f042 4280 orr.w r2, r2, #1073741824 ; 0x40000000
+ 8001fc6: 615a str r2, [r3, #20]
+
+ // include "launch" to make them take effect NOW
+ SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
+ 8001fc8: 695a ldr r2, [r3, #20]
+ 8001fca: f042 6200 orr.w r2, r2, #134217728 ; 0x8000000
+ 8001fce: 615a str r2, [r3, #20]
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
+ 8001fd0: 691a ldr r2, [r3, #16]
+ 8001fd2: 03d1 lsls r1, r2, #15
+ 8001fd4: d4fc bmi.n 8001fd0 <flash_ob_lock.part.0+0x34>
+ uint32_t error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
+ 8001fd6: 6919 ldr r1, [r3, #16]
+ if(error) {
+ 8001fd8: 4a05 ldr r2, [pc, #20] ; (8001ff0 <flash_ob_lock.part.0+0x54>)
+ 8001fda: 4211 tst r1, r2
+ 8001fdc: d104 bne.n 8001fe8 <flash_ob_lock.part.0+0x4c>
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
+ 8001fde: 691a ldr r2, [r3, #16]
+ 8001fe0: 07d2 lsls r2, r2, #31
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ 8001fe2: bf44 itt mi
+ 8001fe4: 2201 movmi r2, #1
+ 8001fe6: 611a strmi r2, [r3, #16]
+
+ _flash_wait_done();
+ }
+}
+ 8001fe8: 4770 bx lr
+ 8001fea: bf00 nop
+ 8001fec: 40022000 .word 0x40022000
+ 8001ff0: 0002c3fa .word 0x0002c3fa
+
+08001ff4 <flash_setup0>:
+{
+ 8001ff4: b507 push {r0, r1, r2, lr}
+ memcpy(&_srelocate, &_etext, ((uint32_t)&_erelocate)-(uint32_t)&_srelocate);
+ 8001ff6: 4809 ldr r0, [pc, #36] ; (800201c <flash_setup0+0x28>)
+ 8001ff8: 4a09 ldr r2, [pc, #36] ; (8002020 <flash_setup0+0x2c>)
+ 8001ffa: 490a ldr r1, [pc, #40] ; (8002024 <flash_setup0+0x30>)
+ 8001ffc: 1a12 subs r2, r2, r0
+ 8001ffe: f00b fb43 bl 800d688 <memcpy>
+ __HAL_RCC_FLASH_CLK_ENABLE();
+ 8002002: 4b09 ldr r3, [pc, #36] ; (8002028 <flash_setup0+0x34>)
+ 8002004: 6c9a ldr r2, [r3, #72] ; 0x48
+ 8002006: f442 7280 orr.w r2, r2, #256 ; 0x100
+ 800200a: 649a str r2, [r3, #72] ; 0x48
+ 800200c: 6c9b ldr r3, [r3, #72] ; 0x48
+ 800200e: f403 7380 and.w r3, r3, #256 ; 0x100
+ 8002012: 9301 str r3, [sp, #4]
+ 8002014: 9b01 ldr r3, [sp, #4]
+}
+ 8002016: b003 add sp, #12
+ 8002018: f85d fb04 ldr.w pc, [sp], #4
+ 800201c: 2009e000 .word 0x2009e000
+ 8002020: 2009e150 .word 0x2009e150
+ 8002024: 0800ead0 .word 0x0800ead0
+ 8002028: 40021000 .word 0x40021000
+
+0800202c <flash_lock>:
+ SET_BIT(FLASH->CR, FLASH_CR_LOCK);
+ 800202c: 4a02 ldr r2, [pc, #8] ; (8002038 <flash_lock+0xc>)
+ 800202e: 6953 ldr r3, [r2, #20]
+ 8002030: f043 4300 orr.w r3, r3, #2147483648 ; 0x80000000
+ 8002034: 6153 str r3, [r2, #20]
+}
+ 8002036: 4770 bx lr
+ 8002038: 40022000 .word 0x40022000
+
+0800203c <flash_unlock>:
+{
+ 800203c: b508 push {r3, lr}
+ if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) {
+ 800203e: 4b08 ldr r3, [pc, #32] ; (8002060 <flash_unlock+0x24>)
+ 8002040: 695a ldr r2, [r3, #20]
+ 8002042: 2a00 cmp r2, #0
+ 8002044: da0a bge.n 800205c <flash_unlock+0x20>
+ WRITE_REG(FLASH->KEYR, FLASH_KEY1);
+ 8002046: 4a07 ldr r2, [pc, #28] ; (8002064 <flash_unlock+0x28>)
+ 8002048: 609a str r2, [r3, #8]
+ WRITE_REG(FLASH->KEYR, FLASH_KEY2);
+ 800204a: f102 3288 add.w r2, r2, #2290649224 ; 0x88888888
+ 800204e: 609a str r2, [r3, #8]
+ if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) {
+ 8002050: 695b ldr r3, [r3, #20]
+ 8002052: 2b00 cmp r3, #0
+ 8002054: da02 bge.n 800205c <flash_unlock+0x20>
+ INCONSISTENT("failed to unlock");
+ 8002056: 4804 ldr r0, [pc, #16] ; (8002068 <flash_unlock+0x2c>)
+ 8002058: f7fe fcf6 bl 8000a48 <fatal_error>
+}
+ 800205c: bd08 pop {r3, pc}
+ 800205e: bf00 nop
+ 8002060: 40022000 .word 0x40022000
+ 8002064: 45670123 .word 0x45670123
+ 8002068: 0800d760 .word 0x0800d760
+
+0800206c <flash_ob_lock>:
+{
+ 800206c: b510 push {r4, lr}
+ if(!lock) {
+ 800206e: b980 cbnz r0, 8002092 <flash_ob_lock+0x26>
+ if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) {
+ 8002070: 4c0a ldr r4, [pc, #40] ; (800209c <flash_ob_lock+0x30>)
+ 8002072: 6963 ldr r3, [r4, #20]
+ 8002074: 005a lsls r2, r3, #1
+ 8002076: d510 bpl.n 800209a <flash_ob_lock+0x2e>
+ flash_unlock();
+ 8002078: f7ff ffe0 bl 800203c <flash_unlock>
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
+ 800207c: 4b08 ldr r3, [pc, #32] ; (80020a0 <flash_ob_lock+0x34>)
+ 800207e: 60e3 str r3, [r4, #12]
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
+ 8002080: f103 3344 add.w r3, r3, #1145324612 ; 0x44444444
+ 8002084: 60e3 str r3, [r4, #12]
+ if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) {
+ 8002086: 6963 ldr r3, [r4, #20]
+ 8002088: 005b lsls r3, r3, #1
+ 800208a: d506 bpl.n 800209a <flash_ob_lock+0x2e>
+ INCONSISTENT("failed to OB unlock");
+ 800208c: 4805 ldr r0, [pc, #20] ; (80020a4 <flash_ob_lock+0x38>)
+ 800208e: f7fe fcdb bl 8000a48 <fatal_error>
+}
+ 8002092: e8bd 4010 ldmia.w sp!, {r4, lr}
+ 8002096: f7ff bf81 b.w 8001f9c <flash_ob_lock.part.0>
+ 800209a: bd10 pop {r4, pc}
+ 800209c: 40022000 .word 0x40022000
+ 80020a0: 08192a3b .word 0x08192a3b
+ 80020a4: 0800d760 .word 0x0800d760
+
+080020a8 <pick_pairing_secret>:
+
+// pick_pairing_secret()
+//
+ static void
+pick_pairing_secret(void)
+{
+ 80020a8: b570 push {r4, r5, r6, lr}
+ 80020aa: f5ad 6d85 sub.w sp, sp, #1064 ; 0x428
+ // important the RNG works here. ok to call setup multiple times.
+ rng_setup();
+ 80020ae: f000 fb39 bl 8002724 <rng_setup>
+ 80020b2: 24c8 movs r4, #200 ; 0xc8
+#else
+ // Demo to anyone watching that the RNG is working, but likely only
+ // to be seen by production team during initial powerup.
+ uint8_t tmp[1024];
+ for(int i=0; i<200; i++) {
+ rng_buffer(tmp, sizeof(tmp));
+ 80020b4: f44f 6180 mov.w r1, #1024 ; 0x400
+ 80020b8: a80a add r0, sp, #40 ; 0x28
+ 80020ba: f000 fb5f bl 800277c <rng_buffer>
+
+ oled_show_raw(sizeof(tmp), (void *)tmp);
+ 80020be: a90a add r1, sp, #40 ; 0x28
+ 80020c0: f44f 6080 mov.w r0, #1024 ; 0x400
+ 80020c4: f7fe fea0 bl 8000e08 <oled_show_raw>
+ for(int i=0; i<200; i++) {
+ 80020c8: 3c01 subs r4, #1
+ 80020ca: d1f3 bne.n 80020b4 <pick_pairing_secret+0xc>
+ }
+
+ oled_factory_busy();
+ 80020cc: f7fe ff8a bl 8000fe4 <oled_factory_busy>
+#endif
+
+ // .. but don't use those numbers, because those are semi-public now.
+ uint32_t secret[8];
+ for(int i=0; i<8; i++) {
+ 80020d0: ad02 add r5, sp, #8
+ oled_factory_busy();
+ 80020d2: 462e mov r6, r5
+ secret[i] = rng_sample();
+ 80020d4: f000 fb14 bl 8002700 <rng_sample>
+ for(int i=0; i<8; i++) {
+ 80020d8: 3401 adds r4, #1
+ 80020da: 2c08 cmp r4, #8
+ secret[i] = rng_sample();
+ 80020dc: f846 0b04 str.w r0, [r6], #4
+ for(int i=0; i<8; i++) {
+ 80020e0: d1f8 bne.n 80020d4 <pick_pairing_secret+0x2c>
+ }
+
+ // enforce policy that first word is not all ones (so it never
+ // looks like unprogrammed flash).
+ while(secret[0] == ~0) {
+ 80020e2: 682b ldr r3, [r5, #0]
+ 80020e4: 3301 adds r3, #1
+ 80020e6: d00c beq.n 8002102 <pick_pairing_secret+0x5a>
+
+ // Write pairing secret into flash
+ {
+ uint32_t dest = (uint32_t)&rom_secrets->pairing_secret;
+
+ flash_unlock();
+ 80020e8: f7ff ffa8 bl 800203c <flash_unlock>
+ uint32_t dest = (uint32_t)&rom_secrets->pairing_secret;
+ 80020ec: 4c16 ldr r4, [pc, #88] ; (8002148 <pick_pairing_secret+0xa0>)
+ for(int i=0; i<8; i+=2, dest += 8) {
+ 80020ee: 4e17 ldr r6, [pc, #92] ; (800214c <pick_pairing_secret+0xa4>)
+ uint64_t val = (((uint64_t)secret[i]) << 32) | secret[i+1];
+
+ if(flash_burn(dest, val)) {
+ 80020f0: e9d5 3200 ldrd r3, r2, [r5]
+ 80020f4: 4620 mov r0, r4
+ 80020f6: f00b fb2b bl 800d750 <__flash_burn_veneer>
+ 80020fa: b130 cbz r0, 800210a <pick_pairing_secret+0x62>
+ INCONSISTENT("flash fail");
+ 80020fc: 4814 ldr r0, [pc, #80] ; (8002150 <pick_pairing_secret+0xa8>)
+ 80020fe: f7fe fca3 bl 8000a48 <fatal_error>
+ secret[0] = rng_sample();
+ 8002102: f000 fafd bl 8002700 <rng_sample>
+ 8002106: 6028 str r0, [r5, #0]
+ 8002108: e7eb b.n 80020e2 <pick_pairing_secret+0x3a>
+ for(int i=0; i<8; i+=2, dest += 8) {
+ 800210a: 3408 adds r4, #8
+ 800210c: 42b4 cmp r4, r6
+ 800210e: f105 0508 add.w r5, r5, #8
+ 8002112: d1ed bne.n 80020f0 <pick_pairing_secret+0x48>
+ }
+ }
+ flash_lock();
+ 8002114: f7ff ff8a bl 800202c <flash_lock>
+ + sizeof(rom_secrets->mcu_hmac_key);
+
+ STATIC_ASSERT(offsetof(rom_secrets_t, hash_cache_secret) % 8 == 0);
+ STATIC_ASSERT(blen % 8 == 0);
+
+ flash_unlock();
+ 8002118: f7ff ff90 bl 800203c <flash_unlock>
+ uint32_t dest = (uint32_t)&rom_secrets->hash_cache_secret;
+ 800211c: 4c0d ldr r4, [pc, #52] ; (8002154 <pick_pairing_secret+0xac>)
+ for(int i=0; i<blen; i+=8, dest += 8) {
+ 800211e: 4d0e ldr r5, [pc, #56] ; (8002158 <pick_pairing_secret+0xb0>)
+ uint64_t val = ((uint64_t)rng_sample() << 32) | rng_sample();
+ 8002120: f000 faee bl 8002700 <rng_sample>
+ 8002124: 9001 str r0, [sp, #4]
+ 8002126: f000 faeb bl 8002700 <rng_sample>
+
+ if(flash_burn(dest, val)) {
+ 800212a: 9b01 ldr r3, [sp, #4]
+ uint64_t val = ((uint64_t)rng_sample() << 32) | rng_sample();
+ 800212c: 4602 mov r2, r0
+ if(flash_burn(dest, val)) {
+ 800212e: 4620 mov r0, r4
+ 8002130: f00b fb0e bl 800d750 <__flash_burn_veneer>
+ 8002134: 2800 cmp r0, #0
+ 8002136: d1e1 bne.n 80020fc <pick_pairing_secret+0x54>
+ for(int i=0; i<blen; i+=8, dest += 8) {
+ 8002138: 3408 adds r4, #8
+ 800213a: 42ac cmp r4, r5
+ 800213c: d1f0 bne.n 8002120 <pick_pairing_secret+0x78>
+ INCONSISTENT("flash fail");
+ }
+ }
+ flash_lock();
+ 800213e: f7ff ff75 bl 800202c <flash_lock>
+ }
+
+}
+ 8002142: f50d 6d85 add.w sp, sp, #1064 ; 0x428
+ 8002146: bd70 pop {r4, r5, r6, pc}
+ 8002148: 0801c000 .word 0x0801c000
+ 800214c: 0801c020 .word 0x0801c020
+ 8002150: 0800d760 .word 0x0800d760
+ 8002154: 0801c070 .word 0x0801c070
+ 8002158: 0801c0b0 .word 0x0801c0b0
+
+0800215c <flash_save_ae_serial>:
+//
+// Write the serial number of ATECC608 into flash forever.
+//
+ void
+flash_save_ae_serial(const uint8_t serial[9])
+{
+ 800215c: b51f push {r0, r1, r2, r3, r4, lr}
+ 800215e: 4602 mov r2, r0
+ uint64_t tmp[2];
+ memset(&tmp, 0x0, sizeof(tmp));
+ 8002160: 2300 movs r3, #0
+ memcpy(&tmp, serial, 9);
+ 8002162: 6800 ldr r0, [r0, #0]
+ 8002164: 6851 ldr r1, [r2, #4]
+ 8002166: 7a12 ldrb r2, [r2, #8]
+ memset(&tmp, 0x0, sizeof(tmp));
+ 8002168: e9cd 3302 strd r3, r3, [sp, #8]
+ memcpy(&tmp, serial, 9);
+ 800216c: 466b mov r3, sp
+ 800216e: c303 stmia r3!, {r0, r1}
+ 8002170: 701a strb r2, [r3, #0]
+
+ flash_setup0();
+ 8002172: f7ff ff3f bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 8002176: f7ff ff61 bl 800203c <flash_unlock>
+
+ if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[0], tmp[0])) {
+ 800217a: e9dd 2300 ldrd r2, r3, [sp]
+ 800217e: 4809 ldr r0, [pc, #36] ; (80021a4 <flash_save_ae_serial+0x48>)
+ 8002180: f00b fae6 bl 800d750 <__flash_burn_veneer>
+ 8002184: b110 cbz r0, 800218c <flash_save_ae_serial+0x30>
+ INCONSISTENT("fail1");
+ 8002186: 4808 ldr r0, [pc, #32] ; (80021a8 <flash_save_ae_serial+0x4c>)
+ 8002188: f7fe fc5e bl 8000a48 <fatal_error>
+ }
+ if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[1], tmp[1])) {
+ 800218c: e9dd 2302 ldrd r2, r3, [sp, #8]
+ 8002190: 4806 ldr r0, [pc, #24] ; (80021ac <flash_save_ae_serial+0x50>)
+ 8002192: f00b fadd bl 800d750 <__flash_burn_veneer>
+ 8002196: 2800 cmp r0, #0
+ 8002198: d1f5 bne.n 8002186 <flash_save_ae_serial+0x2a>
+ INCONSISTENT("fail2");
+ }
+
+ flash_lock();
+}
+ 800219a: b005 add sp, #20
+ 800219c: f85d eb04 ldr.w lr, [sp], #4
+ flash_lock();
+ 80021a0: f7ff bf44 b.w 800202c <flash_lock>
+ 80021a4: 0801c040 .word 0x0801c040
+ 80021a8: 0800d760 .word 0x0800d760
+ 80021ac: 0801c048 .word 0x0801c048
+
+080021b0 <flash_save_bag_number>:
+//
+// Write bag number (probably a string)
+//
+ void
+flash_save_bag_number(const uint8_t new_number[32])
+{
+ 80021b0: b570 push {r4, r5, r6, lr}
+ 80021b2: b088 sub sp, #32
+ uint32_t dest = (uint32_t)&rom_secrets->bag_number[0];
+ uint64_t tmp[4] = { 0 };
+ uint64_t *src = tmp;
+
+ STATIC_ASSERT(sizeof(tmp) == 32);
+ memcpy(tmp, new_number, 32);
+ 80021b4: 4603 mov r3, r0
+ 80021b6: 466c mov r4, sp
+ 80021b8: f100 0520 add.w r5, r0, #32
+ 80021bc: 6818 ldr r0, [r3, #0]
+ 80021be: 6859 ldr r1, [r3, #4]
+ 80021c0: 4622 mov r2, r4
+ 80021c2: c203 stmia r2!, {r0, r1}
+ 80021c4: 3308 adds r3, #8
+ 80021c6: 42ab cmp r3, r5
+ 80021c8: 4614 mov r4, r2
+ 80021ca: d1f7 bne.n 80021bc <flash_save_bag_number+0xc>
+
+ flash_setup0();
+ 80021cc: f7ff ff12 bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 80021d0: f7ff ff34 bl 800203c <flash_unlock>
+ uint32_t dest = (uint32_t)&rom_secrets->bag_number[0];
+ 80021d4: 4d09 ldr r5, [pc, #36] ; (80021fc <flash_save_bag_number+0x4c>)
+
+ // NOTE: can only write once! No provision for read/check/update.
+ for(int i=0; i<(32/8); i++, dest+=8, src++) {
+ 80021d6: 4e0a ldr r6, [pc, #40] ; (8002200 <flash_save_bag_number+0x50>)
+ 80021d8: 466c mov r4, sp
+ if(flash_burn(dest, *src)) {
+ 80021da: e8f4 2302 ldrd r2, r3, [r4], #8
+ 80021de: 4628 mov r0, r5
+ 80021e0: f00b fab6 bl 800d750 <__flash_burn_veneer>
+ 80021e4: b110 cbz r0, 80021ec <flash_save_bag_number+0x3c>
+ INCONSISTENT("fail write");
+ 80021e6: 4807 ldr r0, [pc, #28] ; (8002204 <flash_save_bag_number+0x54>)
+ 80021e8: f7fe fc2e bl 8000a48 <fatal_error>
+ for(int i=0; i<(32/8); i++, dest+=8, src++) {
+ 80021ec: 3508 adds r5, #8
+ 80021ee: 42b5 cmp r5, r6
+ 80021f0: d1f3 bne.n 80021da <flash_save_bag_number+0x2a>
+ }
+ }
+
+ flash_lock();
+}
+ 80021f2: b008 add sp, #32
+ 80021f4: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr}
+ flash_lock();
+ 80021f8: f7ff bf18 b.w 800202c <flash_lock>
+ 80021fc: 0801c050 .word 0x0801c050
+ 8002200: 0801c070 .word 0x0801c070
+ 8002204: 0800d760 .word 0x0800d760
+
+08002208 <flash_save_se2_data>:
+// Save bunch of stuff related to SE2. Allow updates to sections that are
+// given as ones at this point.
+//
+ void
+flash_save_se2_data(const se2_secrets_t *se2)
+{
+ 8002208: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr}
+ 800220c: 4605 mov r5, r0
+ uint8_t *dest = (uint8_t *)&rom_secrets->se2;
+ 800220e: 4c1a ldr r4, [pc, #104] ; (8002278 <flash_save_se2_data+0x70>)
+ STATIC_ASSERT(offsetof(rom_secrets_t, se2) % 8 == 0);
+
+ flash_setup0();
+ flash_unlock();
+
+ for(int i=0; i<(sizeof(se2_secrets_t)/8); i++, dest+=8, src+=8) {
+ 8002210: f8df 8070 ldr.w r8, [pc, #112] ; 8002284 <flash_save_se2_data+0x7c>
+ flash_setup0();
+ 8002214: f7ff feee bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 8002218: f7ff ff10 bl 800203c <flash_unlock>
+ for(int i=0; i<(sizeof(se2_secrets_t)/8); i++, dest+=8, src+=8) {
+ 800221c: 1b2d subs r5, r5, r4
+ 800221e: eb05 0c04 add.w ip, r5, r4
+ uint64_t val;
+ memcpy(&val, src, sizeof(val));
+ 8002222: 5928 ldr r0, [r5, r4]
+ 8002224: f8dc 1004 ldr.w r1, [ip, #4]
+ 8002228: 466b mov r3, sp
+
+ // don't write if all ones or already written correctly
+ if(val == ~0) continue;
+ 800222a: f1b1 3fff cmp.w r1, #4294967295 ; 0xffffffff
+ 800222e: bf08 it eq
+ 8002230: f1b0 3fff cmpeq.w r0, #4294967295 ; 0xffffffff
+ memcpy(&val, src, sizeof(val));
+ 8002234: c303 stmia r3!, {r0, r1}
+ if(val == ~0) continue;
+ 8002236: 4607 mov r7, r0
+ 8002238: 460e mov r6, r1
+ 800223a: d015 beq.n 8002268 <flash_save_se2_data+0x60>
+ if(check_equal(dest, src, 8)) continue;
+ 800223c: 2208 movs r2, #8
+ 800223e: 4661 mov r1, ip
+ 8002240: 4620 mov r0, r4
+ 8002242: f000 fa4c bl 80026de <check_equal>
+ 8002246: b978 cbnz r0, 8002268 <flash_save_se2_data+0x60>
+
+ // can't write if not ones already
+ ASSERT(check_all_ones(dest, 8));
+ 8002248: 2108 movs r1, #8
+ 800224a: 4620 mov r0, r4
+ 800224c: f000 fa2e bl 80026ac <check_all_ones>
+ 8002250: b910 cbnz r0, 8002258 <flash_save_se2_data+0x50>
+ 8002252: 480a ldr r0, [pc, #40] ; (800227c <flash_save_se2_data+0x74>)
+
+ if(flash_burn((uint32_t)dest, val)) {
+ INCONSISTENT("fail write");
+ 8002254: f7fe fbf8 bl 8000a48 <fatal_error>
+ if(flash_burn((uint32_t)dest, val)) {
+ 8002258: 463a mov r2, r7
+ 800225a: 4633 mov r3, r6
+ 800225c: 4620 mov r0, r4
+ 800225e: f00b fa77 bl 800d750 <__flash_burn_veneer>
+ 8002262: b108 cbz r0, 8002268 <flash_save_se2_data+0x60>
+ INCONSISTENT("fail write");
+ 8002264: 4806 ldr r0, [pc, #24] ; (8002280 <flash_save_se2_data+0x78>)
+ 8002266: e7f5 b.n 8002254 <flash_save_se2_data+0x4c>
+ for(int i=0; i<(sizeof(se2_secrets_t)/8); i++, dest+=8, src+=8) {
+ 8002268: 3408 adds r4, #8
+ 800226a: 4544 cmp r4, r8
+ 800226c: d1d7 bne.n 800221e <flash_save_se2_data+0x16>
+ }
+ }
+
+ flash_lock();
+}
+ 800226e: b002 add sp, #8
+ 8002270: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr}
+ flash_lock();
+ 8002274: f7ff beda b.w 800202c <flash_lock>
+ 8002278: 0801c0b0 .word 0x0801c0b0
+ 800227c: 0800e466 .word 0x0800e466
+ 8002280: 0800d760 .word 0x0800d760
+ 8002284: 0801c190 .word 0x0801c190
+
+08002288 <flash_setup>:
+//
+// This is really a state-machine, to recover boards that are booted w/ missing AE chip.
+//
+ void
+flash_setup(void)
+{
+ 8002288: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr}
+
+ // see if we have picked a pairing secret yet.
+ // NOTE: critical section for glitching (at least in past versions)
+ // - check_all.. functions have a rng_delay in them already
+ rng_delay();
+ bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
+ 800228c: 4d3e ldr r5, [pc, #248] ; (8002388 <flash_setup+0x100>)
+{
+ 800228e: b088 sub sp, #32
+ flash_setup0();
+ 8002290: f7ff feb0 bl 8001ff4 <flash_setup0>
+ rng_delay();
+ 8002294: f000 fa88 bl 80027a8 <rng_delay>
+ bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
+ 8002298: 2120 movs r1, #32
+ 800229a: 4628 mov r0, r5
+ 800229c: f000 fa06 bl 80026ac <check_all_ones>
+ bool zeroed_ps = check_all_zeros(rom_secrets->pairing_secret, 32);
+ 80022a0: 2120 movs r1, #32
+ bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
+ 80022a2: 4606 mov r6, r0
+ bool zeroed_ps = check_all_zeros(rom_secrets->pairing_secret, 32);
+ 80022a4: 4628 mov r0, r5
+ 80022a6: f000 fa0b bl 80026c0 <check_all_zeros>
+ bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
+ 80022aa: 2120 movs r1, #32
+ bool zeroed_ps = check_all_zeros(rom_secrets->pairing_secret, 32);
+ 80022ac: 4607 mov r7, r0
+ bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
+ 80022ae: 4837 ldr r0, [pc, #220] ; (800238c <flash_setup+0x104>)
+ 80022b0: f000 f9fc bl 80026ac <check_all_ones>
+ bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0);
+ 80022b4: e9d5 8510 ldrd r8, r5, [r5, #64] ; 0x40
+ bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
+ 80022b8: 4604 mov r4, r0
+ rng_delay();
+ 80022ba: f000 fa75 bl 80027a8 <rng_delay>
+
+ if(zeroed_ps) {
+ 80022be: b127 cbz r7, 80022ca <flash_setup+0x42>
+ // fast brick process leaves us w/ zero pairing secret
+ oled_show(screen_brick);
+ 80022c0: 4833 ldr r0, [pc, #204] ; (8002390 <flash_setup+0x108>)
+ 80022c2: f7fe fdcd bl 8000e60 <oled_show>
+ LOCKUP_FOREVER();
+ 80022c6: bf30 wfi
+ 80022c8: e7fd b.n 80022c6 <flash_setup+0x3e>
+ }
+
+ if(blank_ps) {
+ 80022ca: b10e cbz r6, 80022d0 <flash_setup+0x48>
+ // get some good entropy, save it.
+ pick_pairing_secret();
+ 80022cc: f7ff feec bl 80020a8 <pick_pairing_secret>
+
+ blank_ps = false;
+ }
+
+ if(blank_xor || blank_ae) {
+ 80022d0: b92c cbnz r4, 80022de <flash_setup+0x56>
+ 80022d2: f1b5 3fff cmp.w r5, #4294967295 ; 0xffffffff
+ 80022d6: bf08 it eq
+ 80022d8: f1b8 3fff cmpeq.w r8, #4294967295 ; 0xffffffff
+ 80022dc: d12f bne.n 800233e <flash_setup+0xb6>
+
+ // setup the SE2 (mostly). handles failures by dying
+ se2_setup_config();
+ 80022de: f005 fb07 bl 80078f0 <se2_setup_config>
+
+ // configure and lock-down the SE1
+ int rv = ae_setup_config();
+ 80022e2: f001 f99b bl 800361c <ae_setup_config>
+ 80022e6: 4605 mov r5, r0
+
+ rng_delay();
+ 80022e8: f000 fa5e bl 80027a8 <rng_delay>
+ if(rv) {
+ 80022ec: b13d cbz r5, 80022fe <flash_setup+0x76>
+ // Hardware fail speaking to AE chip ... be careful not to brick here.
+ // Do not continue!! We might fix the board, or add missing pullup, etc.
+ oled_show(screen_se1_issue);
+ 80022ee: 4829 ldr r0, [pc, #164] ; (8002394 <flash_setup+0x10c>)
+ 80022f0: f7fe fdb6 bl 8000e60 <oled_show>
+ puts("SE1 config fail");
+ 80022f4: 4828 ldr r0, [pc, #160] ; (8002398 <flash_setup+0x110>)
+ 80022f6: f002 fd8b bl 8004e10 <puts>
+
+ LOCKUP_FOREVER();
+ 80022fa: bf30 wfi
+ 80022fc: e7fd b.n 80022fa <flash_setup+0x72>
+ }
+
+ rng_delay();
+ 80022fe: f000 fa53 bl 80027a8 <rng_delay>
+ if(blank_xor) {
+ 8002302: b1a4 cbz r4, 800232e <flash_setup+0xa6>
+ flash_unlock();
+ 8002304: f7ff fe9a bl 800203c <flash_unlock>
+ uint64_t *src = (uint64_t *)&rom_secrets->pairing_secret;
+ 8002308: 4c1f ldr r4, [pc, #124] ; (8002388 <flash_setup+0x100>)
+ for(int i=0; i<(32/8); i++, dest+=8, src++) {
+ 800230a: 4d20 ldr r5, [pc, #128] ; (800238c <flash_setup+0x104>)
+ uint64_t val = ~(*src);
+ 800230c: e9d4 2300 ldrd r2, r3, [r4]
+ if(flash_burn(dest, val)) {
+ 8002310: f104 0020 add.w r0, r4, #32
+ 8002314: 43d2 mvns r2, r2
+ 8002316: 43db mvns r3, r3
+ 8002318: f00b fa1a bl 800d750 <__flash_burn_veneer>
+ 800231c: b110 cbz r0, 8002324 <flash_setup+0x9c>
+ INCONSISTENT("flash xor fail");
+ 800231e: 481f ldr r0, [pc, #124] ; (800239c <flash_setup+0x114>)
+ 8002320: f7fe fb92 bl 8000a48 <fatal_error>
+ for(int i=0; i<(32/8); i++, dest+=8, src++) {
+ 8002324: 3408 adds r4, #8
+ 8002326: 42ac cmp r4, r5
+ 8002328: d1f0 bne.n 800230c <flash_setup+0x84>
+ flash_lock();
+ 800232a: f7ff fe7f bl 800202c <flash_lock>
+ // Q: just do it (we warned them)
+ extern void turn_power_off(void);
+ turn_power_off();
+#else
+ // Mk: operator must do it
+ oled_show(screen_replug);
+ 800232e: 481c ldr r0, [pc, #112] ; (80023a0 <flash_setup+0x118>)
+ 8002330: f7fe fd96 bl 8000e60 <oled_show>
+ puts("replug required");
+ 8002334: 481b ldr r0, [pc, #108] ; (80023a4 <flash_setup+0x11c>)
+ 8002336: f002 fd6b bl 8004e10 <puts>
+ LOCKUP_FOREVER();
+ 800233a: bf30 wfi
+ 800233c: e7fd b.n 800233a <flash_setup+0xb2>
+
+ rng_delay();
+ if(!blank_ps && !blank_xor) {
+ // check the XOR value also written: 2 phase commit
+ uint8_t tmp[32];
+ memcpy(tmp, rom_secrets->pairing_secret, 32);
+ 800233e: 4d12 ldr r5, [pc, #72] ; (8002388 <flash_setup+0x100>)
+ rng_delay();
+ 8002340: f000 fa32 bl 80027a8 <rng_delay>
+ memcpy(tmp, rom_secrets->pairing_secret, 32);
+ 8002344: cd0f ldmia r5!, {r0, r1, r2, r3}
+ 8002346: 466c mov r4, sp
+ 8002348: c40f stmia r4!, {r0, r1, r2, r3}
+ 800234a: e895 000f ldmia.w r5, {r0, r1, r2, r3}
+ 800234e: e884 000f stmia.w r4, {r0, r1, r2, r3}
+ 8002352: 466b mov r3, sp
+ 8002354: 4a0d ldr r2, [pc, #52] ; (800238c <flash_setup+0x104>)
+bool check_equal(const void *aV, const void *bV, int len);
+
+// XOR-mixin more bytes; acc = acc XOR more for each byte
+void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
+{
+ for(; len; len--, more++, acc++) {
+ 8002356: 4c14 ldr r4, [pc, #80] ; (80023a8 <flash_setup+0x120>)
+ 8002358: 4618 mov r0, r3
+ *(acc) ^= *(more);
+ 800235a: 7819 ldrb r1, [r3, #0]
+ 800235c: f812 5b01 ldrb.w r5, [r2], #1
+ 8002360: 4069 eors r1, r5
+ for(; len; len--, more++, acc++) {
+ 8002362: 42a2 cmp r2, r4
+ *(acc) ^= *(more);
+ 8002364: f803 1b01 strb.w r1, [r3], #1
+ for(; len; len--, more++, acc++) {
+ 8002368: d1f7 bne.n 800235a <flash_setup+0xd2>
+ xor_mixin(tmp, rom_secrets->pairing_secret_xor, 32);
+
+ if(!check_all_ones(tmp, 32)) {
+ 800236a: 2120 movs r1, #32
+ 800236c: f000 f99e bl 80026ac <check_all_ones>
+ 8002370: b938 cbnz r0, 8002382 <flash_setup+0xfa>
+ oled_show(screen_corrupt);
+ 8002372: 480e ldr r0, [pc, #56] ; (80023ac <flash_setup+0x124>)
+ 8002374: f7fe fd74 bl 8000e60 <oled_show>
+ puts("corrupt pair sec");
+ 8002378: 480d ldr r0, [pc, #52] ; (80023b0 <flash_setup+0x128>)
+ 800237a: f002 fd49 bl 8004e10 <puts>
+
+ // dfu won't save them here, so just die
+ LOCKUP_FOREVER();
+ 800237e: bf30 wfi
+ 8002380: e7fd b.n 800237e <flash_setup+0xf6>
+ // That's fine if we intend to ship units locked already.
+
+ // Do NOT do write every boot, as it might wear-out
+ // the flash bits in OB.
+
+}
+ 8002382: b008 add sp, #32
+ 8002384: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc}
+ 8002388: 0801c000 .word 0x0801c000
+ 800238c: 0801c020 .word 0x0801c020
+ 8002390: 0800d891 .word 0x0800d891
+ 8002394: 0800dfad .word 0x0800dfad
+ 8002398: 0800e660 .word 0x0800e660
+ 800239c: 0800d760 .word 0x0800d760
+ 80023a0: 0800df4c .word 0x0800df4c
+ 80023a4: 0800e670 .word 0x0800e670
+ 80023a8: 0801c040 .word 0x0801c040
+ 80023ac: 0800d8fb .word 0x0800d8fb
+ 80023b0: 0800e680 .word 0x0800e680
+
+080023b4 <flash_lockdown_hard>:
+//
+// This is a one-way trip. Might need power cycle to (fully?) take effect.
+//
+ void
+flash_lockdown_hard(uint8_t rdp_level_code)
+{
+ 80023b4: b510 push {r4, lr}
+ 80023b6: 4604 mov r4, r0
+#if RELEASE
+ flash_setup0();
+ 80023b8: f7ff fe1c bl 8001ff4 <flash_setup0>
+
+ // see FLASH_OB_WRPConfig()
+
+ flash_ob_lock(false);
+ 80023bc: 2000 movs r0, #0
+ 80023be: f7ff fe55 bl 800206c <flash_ob_lock>
+ // lock first 128k-8k against any writes
+ FLASH->WRP1AR = (num_pages_locked << 16);
+ 80023c2: 4b08 ldr r3, [pc, #32] ; (80023e4 <flash_lockdown_hard+0x30>)
+ 80023c4: f44f 2260 mov.w r2, #917504 ; 0xe0000
+ 80023c8: 62da str r2, [r3, #44] ; 0x2c
+ FLASH->WRP1BR = 0xff; // unused.
+ 80023ca: 22ff movs r2, #255 ; 0xff
+ 80023cc: 631a str r2, [r3, #48] ; 0x30
+ FLASH->WRP2AR = 0xff; // unused.
+ 80023ce: 64da str r2, [r3, #76] ; 0x4c
+ FLASH->WRP2BR = 0xff; // unused.
+ 80023d0: 651a str r2, [r3, #80] ; 0x50
+ // the RDP level is decreased from Level 1 to Level 0)."
+ // - D-bus access blocked, even for code running inside the PCROP area! (AN4758)
+ // So literal values and constant tables and such would need special linking.
+
+ // set protection level
+ uint32_t was = FLASH->OPTR & ~0xff;
+ 80023d2: 6a1a ldr r2, [r3, #32]
+ 80023d4: f022 02ff bic.w r2, r2, #255 ; 0xff
+ FLASH->OPTR = was | rdp_level_code; // select level X, other values as observed
+ 80023d8: 4322 orrs r2, r4
+ 80023da: 621a str r2, [r3, #32]
+#else
+ puts2("flash_lockdown_hard(");
+ puthex2(rdp_level_code);
+ puts(") skipped");
+#endif
+}
+ 80023dc: e8bd 4010 ldmia.w sp!, {r4, lr}
+ 80023e0: f7ff bddc b.w 8001f9c <flash_ob_lock.part.0>
+ 80023e4: 40022000 .word 0x40022000
+
+080023e8 <record_highwater_version>:
+
+// record_highwater_version()
+//
+ int
+record_highwater_version(const uint8_t timestamp[8])
+{
+ 80023e8: b537 push {r0, r1, r2, r4, r5, lr}
+ const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;
+
+ ASSERT(timestamp[0] < 0x40);
+ ASSERT(timestamp[0] >= 0x10);
+ 80023ea: 7802 ldrb r2, [r0, #0]
+ 80023ec: 3a10 subs r2, #16
+ 80023ee: 2a2f cmp r2, #47 ; 0x2f
+{
+ 80023f0: 4603 mov r3, r0
+ ASSERT(timestamp[0] >= 0x10);
+ 80023f2: d902 bls.n 80023fa <record_highwater_version+0x12>
+ ASSERT(timestamp[0] < 0x40);
+ 80023f4: 4810 ldr r0, [pc, #64] ; (8002438 <record_highwater_version+0x50>)
+ 80023f6: f7fe fb27 bl 8000a48 <fatal_error>
+
+ uint64_t val = 0;
+ memcpy(&val, timestamp, 8);
+ 80023fa: 6800 ldr r0, [r0, #0]
+ 80023fc: 6859 ldr r1, [r3, #4]
+ const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;
+ 80023fe: 4c0f ldr r4, [pc, #60] ; (800243c <record_highwater_version+0x54>)
+
+ // just write to first blank slot we can find.
+ for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
+ 8002400: 4d0f ldr r5, [pc, #60] ; (8002440 <record_highwater_version+0x58>)
+ memcpy(&val, timestamp, 8);
+ 8002402: 466a mov r2, sp
+ 8002404: c203 stmia r2!, {r0, r1}
+ if(check_all_ones(otp, 8)) {
+ 8002406: 2108 movs r1, #8
+ 8002408: 4620 mov r0, r4
+ 800240a: f000 f94f bl 80026ac <check_all_ones>
+ 800240e: b168 cbz r0, 800242c <record_highwater_version+0x44>
+ // write here.
+ flash_setup0();
+ 8002410: f7ff fdf0 bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 8002414: f7ff fe12 bl 800203c <flash_unlock>
+ flash_burn((uint32_t)otp, val);
+ 8002418: e9dd 2300 ldrd r2, r3, [sp]
+ 800241c: 4620 mov r0, r4
+ 800241e: f00b f997 bl 800d750 <__flash_burn_veneer>
+ flash_lock();
+ 8002422: f7ff fe03 bl 800202c <flash_lock>
+
+ return 0;
+ 8002426: 2000 movs r0, #0
+ }
+ }
+
+ // no space.
+ return 1;
+}
+ 8002428: b003 add sp, #12
+ 800242a: bd30 pop {r4, r5, pc}
+ for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
+ 800242c: 3408 adds r4, #8
+ 800242e: 42ac cmp r4, r5
+ 8002430: d1e9 bne.n 8002406 <record_highwater_version+0x1e>
+ return 1;
+ 8002432: 2001 movs r0, #1
+ 8002434: e7f8 b.n 8002428 <record_highwater_version+0x40>
+ 8002436: bf00 nop
+ 8002438: 0800e466 .word 0x0800e466
+ 800243c: 1fff7000 .word 0x1fff7000
+ 8002440: 1fff7400 .word 0x1fff7400
+
+08002444 <mcu_key_get>:
+
+// mcu_key_get()
+//
+ const mcu_key_t *
+mcu_key_get(bool *valid)
+{
+ 8002444: b570 push {r4, r5, r6, lr}
+ // get current "mcu_key" value; first byte will never be 0x0 or 0xff
+ // - except if no key set yet/recently wiped
+ // - if none set, returns ptr to first available slot which will be all ones
+ const mcu_key_t *ptr = MCU_KEYS, *avail=NULL;
+
+ for(int i=0; i<NUM_MCU_KEYS; i++, ptr++) {
+ 8002446: 4a0d ldr r2, [pc, #52] ; (800247c <mcu_key_get+0x38>)
+ const mcu_key_t *ptr = MCU_KEYS, *avail=NULL;
+ 8002448: 4c0d ldr r4, [pc, #52] ; (8002480 <mcu_key_get+0x3c>)
+{
+ 800244a: 4606 mov r6, r0
+ const mcu_key_t *ptr = MCU_KEYS, *avail=NULL;
+ 800244c: 2500 movs r5, #0
+ if(ptr->value[0] == 0xff) {
+ 800244e: 7823 ldrb r3, [r4, #0]
+ 8002450: 2bff cmp r3, #255 ; 0xff
+ 8002452: d10b bne.n 800246c <mcu_key_get+0x28>
+ if(!avail) {
+ 8002454: 2d00 cmp r5, #0
+ 8002456: bf08 it eq
+ 8002458: 4625 moveq r5, r4
+ for(int i=0; i<NUM_MCU_KEYS; i++, ptr++) {
+ 800245a: 3420 adds r4, #32
+ 800245c: 4294 cmp r4, r2
+ 800245e: d1f6 bne.n 800244e <mcu_key_get+0xa>
+ *valid = true;
+ return ptr;
+ }
+ }
+
+ rng_delay();
+ 8002460: f000 f9a2 bl 80027a8 <rng_delay>
+ *valid = false;
+ 8002464: 2300 movs r3, #0
+ 8002466: 7033 strb r3, [r6, #0]
+ return avail;
+ 8002468: 462c mov r4, r5
+ 800246a: e005 b.n 8002478 <mcu_key_get+0x34>
+ } else if(ptr->value[0] != 0x00) {
+ 800246c: 2b00 cmp r3, #0
+ 800246e: d0f4 beq.n 800245a <mcu_key_get+0x16>
+ rng_delay();
+ 8002470: f000 f99a bl 80027a8 <rng_delay>
+ *valid = true;
+ 8002474: 2301 movs r3, #1
+ 8002476: 7033 strb r3, [r6, #0]
+}
+ 8002478: 4620 mov r0, r4
+ 800247a: bd70 pop {r4, r5, r6, pc}
+ 800247c: 08020000 .word 0x08020000
+ 8002480: 0801e000 .word 0x0801e000
+
+08002484 <mcu_key_clear>:
+
+// mcu_key_clear()
+//
+ void
+mcu_key_clear(const mcu_key_t *cur)
+{
+ 8002484: b513 push {r0, r1, r4, lr}
+ if(!cur) {
+ 8002486: 4604 mov r4, r0
+ 8002488: b938 cbnz r0, 800249a <mcu_key_clear+0x16>
+ bool valid;
+ cur = mcu_key_get(&valid);
+ 800248a: f10d 0007 add.w r0, sp, #7
+ 800248e: f7ff ffd9 bl 8002444 <mcu_key_get>
+
+ if(!valid) return;
+ 8002492: f89d 3007 ldrb.w r3, [sp, #7]
+ cur = mcu_key_get(&valid);
+ 8002496: 4604 mov r4, r0
+ if(!valid) return;
+ 8002498: b1fb cbz r3, 80024da <mcu_key_clear+0x56>
+ }
+
+ // no delays here since decision has been made, and don't
+ // want to give them more time to interrupt us
+ flash_setup0();
+ 800249a: f7ff fdab bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 800249e: f7ff fdcd bl 800203c <flash_unlock>
+ uint32_t pos = (uint32_t)cur;
+ flash_burn(pos, 0); pos += 8;
+ 80024a2: 2200 movs r2, #0
+ 80024a4: 2300 movs r3, #0
+ 80024a6: 4620 mov r0, r4
+ 80024a8: f00b f952 bl 800d750 <__flash_burn_veneer>
+ flash_burn(pos, 0); pos += 8;
+ 80024ac: 2200 movs r2, #0
+ 80024ae: 2300 movs r3, #0
+ 80024b0: f104 0008 add.w r0, r4, #8
+ 80024b4: f00b f94c bl 800d750 <__flash_burn_veneer>
+ flash_burn(pos, 0); pos += 8;
+ 80024b8: 2200 movs r2, #0
+ 80024ba: 2300 movs r3, #0
+ 80024bc: f104 0010 add.w r0, r4, #16
+ 80024c0: f00b f946 bl 800d750 <__flash_burn_veneer>
+ flash_burn(pos, 0);
+ 80024c4: 2200 movs r2, #0
+ 80024c6: 2300 movs r3, #0
+ 80024c8: f104 0018 add.w r0, r4, #24
+ 80024cc: f00b f940 bl 800d750 <__flash_burn_veneer>
+ flash_lock();
+}
+ 80024d0: b002 add sp, #8
+ 80024d2: e8bd 4010 ldmia.w sp!, {r4, lr}
+ flash_lock();
+ 80024d6: f7ff bda9 b.w 800202c <flash_lock>
+}
+ 80024da: b002 add sp, #8
+ 80024dc: bd10 pop {r4, pc}
+ ...
+
+080024e0 <mcu_key_usage>:
+
+// mcu_key_usage()
+//
+ void
+mcu_key_usage(int *avail_out, int *consumed_out, int *total_out)
+{
+ 80024e0: b5f0 push {r4, r5, r6, r7, lr}
+ const mcu_key_t *ptr = MCU_KEYS;
+ int avail = 0, used = 0;
+ 80024e2: 2300 movs r3, #0
+ const mcu_key_t *ptr = MCU_KEYS;
+ 80024e4: 4c09 ldr r4, [pc, #36] ; (800250c <mcu_key_usage+0x2c>)
+
+ for(int i=0; i<NUM_MCU_KEYS; i++, ptr++) {
+ 80024e6: 4f0a ldr r7, [pc, #40] ; (8002510 <mcu_key_usage+0x30>)
+ int avail = 0, used = 0;
+ 80024e8: 461d mov r5, r3
+ if(ptr->value[0] == 0xff) {
+ 80024ea: 7826 ldrb r6, [r4, #0]
+ 80024ec: 2eff cmp r6, #255 ; 0xff
+ 80024ee: d109 bne.n 8002504 <mcu_key_usage+0x24>
+ avail ++;
+ 80024f0: 3501 adds r5, #1
+ for(int i=0; i<NUM_MCU_KEYS; i++, ptr++) {
+ 80024f2: 3420 adds r4, #32
+ 80024f4: 42bc cmp r4, r7
+ 80024f6: d1f8 bne.n 80024ea <mcu_key_usage+0xa>
+ } else if(ptr->value[0] == 0x00) {
+ used ++;
+ }
+ }
+
+ *avail_out = avail;
+ 80024f8: 6005 str r5, [r0, #0]
+ *consumed_out = used;
+ 80024fa: 600b str r3, [r1, #0]
+ *total_out = NUM_MCU_KEYS;
+ 80024fc: f44f 7380 mov.w r3, #256 ; 0x100
+ 8002500: 6013 str r3, [r2, #0]
+}
+ 8002502: bdf0 pop {r4, r5, r6, r7, pc}
+ } else if(ptr->value[0] == 0x00) {
+ 8002504: 2e00 cmp r6, #0
+ 8002506: d1f4 bne.n 80024f2 <mcu_key_usage+0x12>
+ used ++;
+ 8002508: 3301 adds r3, #1
+ 800250a: e7f2 b.n 80024f2 <mcu_key_usage+0x12>
+ 800250c: 0801e000 .word 0x0801e000
+ 8002510: 08020000 .word 0x08020000
+
+08002514 <mcu_key_pick>:
+
+// mcu_key_pick()
+//
+ const mcu_key_t *
+mcu_key_pick(void)
+{
+ 8002514: b5f0 push {r4, r5, r6, r7, lr}
+ 8002516: b08b sub sp, #44 ; 0x2c
+ mcu_key_t n;
+
+ // get some good entropy, and whiten it just in case.
+ do {
+ rng_buffer(n.value, 32);
+ 8002518: ad02 add r5, sp, #8
+ 800251a: 2120 movs r1, #32
+ 800251c: 4628 mov r0, r5
+ 800251e: f000 f92d bl 800277c <rng_buffer>
+ sha256_single(n.value, 32, n.value);
+ 8002522: 462a mov r2, r5
+ 8002524: 2120 movs r1, #32
+ 8002526: 4628 mov r0, r5
+ 8002528: f003 f84a bl 80055c0 <sha256_single>
+ sha256_single(n.value, 32, n.value);
+ 800252c: 462a mov r2, r5
+ 800252e: 2120 movs r1, #32
+ 8002530: 4628 mov r0, r5
+ 8002532: f003 f845 bl 80055c0 <sha256_single>
+ } while(n.value[0] == 0x0 || n.value[0] == 0xff);
+ 8002536: f89d 3008 ldrb.w r3, [sp, #8]
+ 800253a: 3b01 subs r3, #1
+ 800253c: b2db uxtb r3, r3
+ 800253e: 2bfd cmp r3, #253 ; 0xfd
+ 8002540: d8eb bhi.n 800251a <mcu_key_pick+0x6>
+
+ int err = 0;
+ const mcu_key_t *cur;
+
+ do {
+ bool valid = false;
+ 8002542: 2300 movs r3, #0
+ cur = mcu_key_get(&valid);
+ 8002544: 4668 mov r0, sp
+ bool valid = false;
+ 8002546: f88d 3000 strb.w r3, [sp]
+ cur = mcu_key_get(&valid);
+ 800254a: f7ff ff7b bl 8002444 <mcu_key_get>
+
+ if(!cur) {
+ 800254e: 4604 mov r4, r0
+ 8002550: b938 cbnz r0, 8002562 <mcu_key_pick+0x4e>
+ // no free slots. we are brick.
+ puts("mcu full");
+ 8002552: 4828 ldr r0, [pc, #160] ; (80025f4 <mcu_key_pick+0xe0>)
+ 8002554: f002 fc5c bl 8004e10 <puts>
+ oled_show(screen_brick);
+ 8002558: 4827 ldr r0, [pc, #156] ; (80025f8 <mcu_key_pick+0xe4>)
+ 800255a: f7fe fc81 bl 8000e60 <oled_show>
+
+ LOCKUP_FOREVER();
+ 800255e: bf30 wfi
+ 8002560: e7fd b.n 800255e <mcu_key_pick+0x4a>
+ }
+
+ if(valid) {
+ 8002562: f89d 3000 ldrb.w r3, [sp]
+ 8002566: b14b cbz r3, 800257c <mcu_key_pick+0x68>
+ // clear existing key, if it's defined.
+ ASSERT(cur->value[0] != 0x00);
+ 8002568: 7803 ldrb r3, [r0, #0]
+ 800256a: 3b01 subs r3, #1
+ 800256c: b2db uxtb r3, r3
+ 800256e: 2bfd cmp r3, #253 ; 0xfd
+ 8002570: d902 bls.n 8002578 <mcu_key_pick+0x64>
+ 8002572: 4822 ldr r0, [pc, #136] ; (80025fc <mcu_key_pick+0xe8>)
+ 8002574: f7fe fa68 bl 8000a48 <fatal_error>
+ ASSERT(cur->value[0] != 0xff);
+
+ mcu_key_clear(cur);
+ 8002578: f7ff ff84 bl 8002484 <mcu_key_clear>
+ continue;
+ }
+ } while(0);
+
+ // burn it
+ flash_setup0();
+ 800257c: f7ff fd3a bl 8001ff4 <flash_setup0>
+ flash_unlock();
+ 8002580: f7ff fd5c bl 800203c <flash_unlock>
+ uint32_t pos = (uint32_t)cur;
+ const uint8_t *fr = n.value;
+
+ for(int i=0; i<32; i+= 8, pos += 8, fr += 8) {
+ 8002584: 2700 movs r7, #0
+ uint64_t v;
+ memcpy(&v, fr, sizeof(v));
+ 8002586: 19ea adds r2, r5, r7
+ 8002588: 59e8 ldr r0, [r5, r7]
+ 800258a: 6851 ldr r1, [r2, #4]
+ 800258c: 466b mov r3, sp
+ 800258e: c303 stmia r3!, {r0, r1}
+
+ err = flash_burn(pos, v);
+ 8002590: 19e0 adds r0, r4, r7
+ 8002592: e9dd 2300 ldrd r2, r3, [sp]
+ 8002596: f00b f8db bl 800d750 <__flash_burn_veneer>
+ if(err) break;
+ 800259a: 4606 mov r6, r0
+ 800259c: b910 cbnz r0, 80025a4 <mcu_key_pick+0x90>
+ for(int i=0; i<32; i+= 8, pos += 8, fr += 8) {
+ 800259e: 3708 adds r7, #8
+ 80025a0: 2f20 cmp r7, #32
+ 80025a2: d1f0 bne.n 8002586 <mcu_key_pick+0x72>
+ }
+ flash_lock();
+ 80025a4: f7ff fd42 bl 800202c <flash_lock>
+
+ // NOTE: Errors not expected, but lets be graceful about them.
+
+ if(err) {
+ 80025a8: b166 cbz r6, 80025c4 <mcu_key_pick+0xb0>
+ // what to do?
+ puts("burn fail: ");
+ 80025aa: 4815 ldr r0, [pc, #84] ; (8002600 <mcu_key_pick+0xec>)
+ 80025ac: f002 fc30 bl 8004e10 <puts>
+ puthex2(err);
+ 80025b0: b2f0 uxtb r0, r6
+ 80025b2: f002 fbd1 bl 8004d58 <puthex2>
+ putchar('\n');
+ 80025b6: 200a movs r0, #10
+ 80025b8: f002 fbb0 bl 8004d1c <putchar>
+ return NULL;
+ }
+
+ if(after != cur || !check_equal(after->value, n.value, 32)) {
+ puts("bad val?");
+ return NULL;
+ 80025bc: 2400 movs r4, #0
+ }
+
+ return cur;
+}
+ 80025be: 4620 mov r0, r4
+ 80025c0: b00b add sp, #44 ; 0x2c
+ 80025c2: bdf0 pop {r4, r5, r6, r7, pc}
+ const mcu_key_t *after = mcu_key_get(&valid);
+ 80025c4: 4668 mov r0, sp
+ bool valid = false;
+ 80025c6: f88d 6000 strb.w r6, [sp]
+ const mcu_key_t *after = mcu_key_get(&valid);
+ 80025ca: f7ff ff3b bl 8002444 <mcu_key_get>
+ if(!valid) {
+ 80025ce: f89d 2000 ldrb.w r2, [sp]
+ 80025d2: b91a cbnz r2, 80025dc <mcu_key_pick+0xc8>
+ puts("!valid?");
+ 80025d4: 480b ldr r0, [pc, #44] ; (8002604 <mcu_key_pick+0xf0>)
+ puts("bad val?");
+ 80025d6: f002 fc1b bl 8004e10 <puts>
+ 80025da: e7ef b.n 80025bc <mcu_key_pick+0xa8>
+ if(after != cur || !check_equal(after->value, n.value, 32)) {
+ 80025dc: 4284 cmp r4, r0
+ 80025de: d001 beq.n 80025e4 <mcu_key_pick+0xd0>
+ puts("bad val?");
+ 80025e0: 4809 ldr r0, [pc, #36] ; (8002608 <mcu_key_pick+0xf4>)
+ 80025e2: e7f8 b.n 80025d6 <mcu_key_pick+0xc2>
+ if(after != cur || !check_equal(after->value, n.value, 32)) {
+ 80025e4: 2220 movs r2, #32
+ 80025e6: 4629 mov r1, r5
+ 80025e8: f000 f879 bl 80026de <check_equal>
+ 80025ec: 2800 cmp r0, #0
+ 80025ee: d1e6 bne.n 80025be <mcu_key_pick+0xaa>
+ 80025f0: e7f6 b.n 80025e0 <mcu_key_pick+0xcc>
+ 80025f2: bf00 nop
+ 80025f4: 0800e691 .word 0x0800e691
+ 80025f8: 0800d891 .word 0x0800d891
+ 80025fc: 0800e466 .word 0x0800e466
+ 8002600: 0800e69a .word 0x0800e69a
+ 8002604: 0800e6a6 .word 0x0800e6a6
+ 8002608: 0800e6ae .word 0x0800e6ae
+
+0800260c <fast_brick>:
+
+// fast_brick()
+//
+ void
+fast_brick(void)
+{
+ 800260c: b538 push {r3, r4, r5, lr}
+#ifndef RELEASE
+ puts2("DISABLED fast brick... ");
+ oled_show(screen_brick);
+#else
+ // do a fast wipe of our key
+ mcu_key_clear(NULL);
+ 800260e: 2000 movs r0, #0
+ 8002610: f7ff ff38 bl 8002484 <mcu_key_clear>
+
+ // brick SE1 for future
+ ae_brick_myself();
+ 8002614: f001 f970 bl 80038f8 <ae_brick_myself>
+
+ // NOTE: could brick SE1 (somewhat) by dec'ing the counter, which will
+ // invalidate all PIN hashes
+
+ // no going back from that -- but for privacy, wipe more stuff
+ oled_show(screen_brick);
+ 8002618: 480e ldr r0, [pc, #56] ; (8002654 <fast_brick+0x48>)
+ uint32_t bot = (uint32_t)MCU_KEYS;
+ flash_page_erase(bot);
+
+ // 2: LFS area first, since holds settings (AES'ed w/ lost key, but yeah)
+ // 3: the firmware, not a secret anyway
+ for(uint32_t pos=(FLASH_BASE + 0x200000 - FLASH_ERASE_SIZE);
+ 800261a: 4c0f ldr r4, [pc, #60] ; (8Why this scored 0/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.